網站首頁 編程語言 正文
前言:
在口袋助理看到了其他部門的同事針對Python2
內存占用做的一點優化工作,自己比較感興趣,遂記錄下。
1.Linux fork簡介
fork是Linux提供的創建子進程的系統調用。為了優化創建進程速度,Linux內核使用了Copy-on-Write
的方式去創建進程,所謂Copy-on-Write
是指執行fork之后,
內核并不立即給子進程分配物理內存空間,而是讓子進程的虛內存映射到父進程的物理內存。僅僅當子進程向地址空間中執行寫入操作時,才給它分配一段物理內存。
通過這種方式既優化了進程創建的時間,又減少了子進程的內存占用。
1.Copy-On-Write策略增加Python多進程內存占用的原因
Python GC采用引用技術的方式去管理對每個對象的引用,每一個被GC跟蹤的對象會由一個PyGC_Head的結構體去表示。如下所示,其中gc_refs
就是每個對象的引用計數值,
當我們在子進程中讀取父進程創建的對象的時候,就會導致子進程的虛地址空間中的gc_refs
加1,從而觸發了內核的缺頁中斷,這是內核就會給子進程創建新的物理內存。
僅僅是簡單的讀取操作就會導致新的內存空間產生。
/* GC information is stored BEFORE the object structure. */ typedef union _gc_head? { ? ? struct { ? ? ? ? union _gc_head *gc_next; ? ? ? ? union _gc_head *gc_prev; ? ? ? ? Py_ssize_t gc_refs; ? ? } gc; ? ? long double dummy; /* force worst-case alignment */ } PyGC_Head;
3.解決辦法
python3的解決方法:
針對這個問題,Python3.7增加了三組API(有instagram團體提交的)[1]。
freeze
用于將GC追蹤的所有對象都移動到永生代(permanent generation)
,之后垃圾回收會忽略這些被設置為永生代的對象。
實際使用中,我們可以在父進程中執行freeze
函數,然后子進程中使用和父進程共享的對象,這樣對象的引用技術就不會增加,從而避免了COW的發生。
python2的解決方法:
- (1) 針對Python2,我們可以簡單的把Python3的相關函數移植過來
- (2) 使用multiprocessing.Array去共享數據。Array會從共享內存中取一段取存儲數據,并不會增加引用技術值,從而觸發COW。
實現方面,Array使用Posix共享內存 + mmap去實現。[3]
#!/usr/bin/env python # coding=utf-8 from multiprocessing import Array import os import sys def foo(): ? ? shared_cache = Array('i', range(0, 100), lock=False) ? ? pid = os.fork() ? ? if pid > 0: ? ? ? ? print("parent:", sys.getrefcount(shared_cache))? ? ? elif pid == 0: ? ? ? ? print("child:", sys.getrefcount(shared_cache)) foo()
到此這篇關于Python垃圾回收及Linux Fork的文章就介紹到這了,更多相關Python垃圾回收及Linux Fork內容請搜索AB教程網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持AB教程網!
參考:
原文鏈接:https://www.cnblogs.com/dennis-wong/p/15782824.html
相關推薦
- 2022-10-27 QT線程QThread的使用介紹_C 語言
- 2022-10-04 SQL語句中的DDL類型的數據庫定義語言操作_MsSql
- 2022-11-04 C/C++中extern函數使用詳解_C 語言
- 2024-02-16 springboot開啟mybatis二級緩存
- 2022-06-07 Python?Numpy庫的超詳細教程_python
- 2023-06-20 Redis?設置密碼無效問題解決_Redis
- 2022-09-05 C語言之關于二維數組在函數中的調用問題_C 語言
- 2022-11-13 詳解Redis?Stream做消息隊列_Redis
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支