Python垃圾回收及Linux?Fork
前言:
在口袋助理看到了其他部門的同事針對Python2
內(nèi)存占用做的一點優(yōu)化工作,自己比較感興趣,遂記錄下。
1.Linux fork簡介
fork是Linux提供的創(chuàng)建子進程的系統(tǒng)調(diào)用。為了優(yōu)化創(chuàng)建進程速度,Linux內(nèi)核使用了Copy-on-Write
的方式去創(chuàng)建進程,所謂Copy-on-Write
是指執(zhí)行fork之后,
內(nèi)核并不立即給子進程分配物理內(nèi)存空間,而是讓子進程的虛內(nèi)存映射到父進程的物理內(nèi)存。僅僅當(dāng)子進程向地址空間中執(zhí)行寫入操作時,才給它分配一段物理內(nèi)存。
通過這種方式既優(yōu)化了進程創(chuàng)建的時間,又減少了子進程的內(nèi)存占用。
1.Copy-On-Write策略增加Python多進程內(nèi)存占用的原因
Python GC采用引用技術(shù)的方式去管理對每個對象的引用,每一個被GC跟蹤的對象會由一個PyGC_Head的結(jié)構(gòu)體去表示。如下所示,其中gc_refs
就是每個對象的引用計數(shù)值,
當(dāng)我們在子進程中讀取父進程創(chuàng)建的對象的時候,就會導(dǎo)致子進程的虛地址空間中的gc_refs
加1,從而觸發(fā)了內(nèi)核的缺頁中斷,這是內(nèi)核就會給子進程創(chuàng)建新的物理內(nèi)存。
僅僅是簡單的讀取操作就會導(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的解決方法:
針對這個問題,Python3.7增加了三組API(有instagram團體提交的)[1]。
freeze
用于將GC追蹤的所有對象都移動到永生代(permanent generation)
,之后垃圾回收會忽略這些被設(shè)置為永生代的對象。
實際使用中,我們可以在父進程中執(zhí)行freeze
函數(shù),然后子進程中使用和父進程共享的對象,這樣對象的引用技術(shù)就不會增加,從而避免了COW的發(fā)生。
python2的解決方法:
- (1) 針對Python2,我們可以簡單的把Python3的相關(guān)函數(shù)移植過來
- (2) 使用multiprocessing.Array去共享數(shù)據(jù)。Array會從共享內(nèi)存中取一段取存儲數(shù)據(jù),并不會增加引用技術(shù)值,從而觸發(fā)COW。
實現(xiàn)方面,Array使用Posix共享內(nèi)存 + mmap去實現(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)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
參考:
1.https://instagram-engineering.com/copy-on-write-friendly-python-garbage-collection-ad6ed5233ddf
2.https://llvllatrix.wordpress.com/2016/02/19/python-vs-copy-on-write/
3.https://github.com/python/cpython/blob/main/Lib/multiprocessing/shared_memory.py
相關(guān)文章
pytorch 調(diào)整某一維度數(shù)據(jù)順序的方法
今天小編就為大家分享一篇pytorch 調(diào)整某一維度數(shù)據(jù)順序的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-12-12Python socket套接字實現(xiàn)C/S模式遠程命令執(zhí)行功能案例
這篇文章主要介紹了Python socket套接字實現(xiàn)C/S模式遠程命令執(zhí)行功能,涉及Python socket套接字編寫服務(wù)器/客戶機模式數(shù)據(jù)傳輸相關(guān)操作技巧,需要的朋友可以參考下2018-07-07