網(wǎng)站首頁 編程語言 正文
前言:
在口袋助理看到了其他部門的同事針對(duì)Python2
內(nèi)存占用做的一點(diǎn)優(yōu)化工作,自己比較感興趣,遂記錄下。
1.Linux fork簡介
fork是Linux提供的創(chuàng)建子進(jìn)程的系統(tǒng)調(diào)用。為了優(yōu)化創(chuàng)建進(jìn)程速度,Linux內(nèi)核使用了Copy-on-Write
的方式去創(chuàng)建進(jìn)程,所謂Copy-on-Write
是指執(zhí)行fork之后,
內(nèi)核并不立即給子進(jìn)程分配物理內(nèi)存空間,而是讓子進(jìn)程的虛內(nèi)存映射到父進(jìn)程的物理內(nèi)存。僅僅當(dāng)子進(jìn)程向地址空間中執(zhí)行寫入操作時(shí),才給它分配一段物理內(nèi)存。
通過這種方式既優(yōu)化了進(jìn)程創(chuàng)建的時(shí)間,又減少了子進(jìn)程的內(nèi)存占用。
1.Copy-On-Write策略增加Python多進(jìn)程內(nèi)存占用的原因
Python GC采用引用技術(shù)的方式去管理對(duì)每個(gè)對(duì)象的引用,每一個(gè)被GC跟蹤的對(duì)象會(huì)由一個(gè)PyGC_Head的結(jié)構(gòu)體去表示。如下所示,其中gc_refs
就是每個(gè)對(duì)象的引用計(jì)數(shù)值,
當(dāng)我們?cè)谧舆M(jìn)程中讀取父進(jìn)程創(chuàng)建的對(duì)象的時(shí)候,就會(huì)導(dǎo)致子進(jìn)程的虛地址空間中的gc_refs
加1,從而觸發(fā)了內(nèi)核的缺頁中斷,這是內(nèi)核就會(huì)給子進(jìn)程創(chuàng)建新的物理內(nèi)存。
僅僅是簡單的讀取操作就會(huì)導(dǎo)致新的內(nèi)存空間產(chǎn)生。
/* 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的解決方法:
針對(duì)這個(gè)問題,Python3.7增加了三組API(有instagram團(tuán)體提交的)[1]。
freeze
用于將GC追蹤的所有對(duì)象都移動(dòng)到永生代(permanent generation)
,之后垃圾回收會(huì)忽略這些被設(shè)置為永生代的對(duì)象。
實(shí)際使用中,我們可以在父進(jìn)程中執(zhí)行freeze
函數(shù),然后子進(jìn)程中使用和父進(jìn)程共享的對(duì)象,這樣對(duì)象的引用技術(shù)就不會(huì)增加,從而避免了COW的發(fā)生。
python2的解決方法:
- (1) 針對(duì)Python2,我們可以簡單的把Python3的相關(guān)函數(shù)移植過來
- (2) 使用multiprocessing.Array去共享數(shù)據(jù)。Array會(huì)從共享內(nèi)存中取一段取存儲(chǔ)數(shù)據(jù),并不會(huì)增加引用技術(shù)值,從而觸發(fā)COW。
實(shí)現(xiàn)方面,Array使用Posix共享內(nèi)存 + mmap去實(shí)現(xiàn)。[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()
到此這篇關(guān)于Python垃圾回收及Linux Fork的文章就介紹到這了,更多相關(guān)Python垃圾回收及Linux Fork內(nèi)容請(qǐng)搜索AB教程網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持AB教程網(wǎng)!
參考:
原文鏈接:https://www.cnblogs.com/dennis-wong/p/15782824.html
相關(guān)推薦
- 2023-11-21 python使用print輸出不同顏色的字體、終端顯示不同顏色字體
- 2022-05-22 小白也可以完成的0基礎(chǔ)部署Nginx服務(wù)_nginx
- 2023-03-05 Python協(xié)程的四種實(shí)現(xiàn)方式總結(jié)_python
- 2022-08-17 go?Cobra命令行工具入門教程_Golang
- 2022-07-03 nginx?緩存使用及配置步驟_nginx
- 2022-09-09 ElasticSearch核心概念_其它綜合
- 2022-07-13 docker基本概念及安裝
- 2022-07-22 mybatis源碼之集成spring原理詳解
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支