[英]Python memory footprint vs. heap size
我在使用python腳本發出大型solr查詢時遇到一些內存問題。 我正在使用solrpy庫與solr服務器接口。 該查詢返回大約80,000條記錄。 發出查詢后,通過頂部氣球查看的python內存占用立即達到190MB。
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
8225 root 16 0 193m 189m 3272 S 0.0 11.2 0:11.31 python
...
此時,通過堆查看的堆概要文件如下所示:
Partition of a set of 163934 objects. Total size = 14157888 bytes.
Index Count % Size % Cumulative % Kind (class / dict of class)
0 80472 49 7401384 52 7401384 52 unicode
1 44923 27 3315928 23 10717312 76 str
...
unicode對象代表查詢中記錄的唯一標識符。 需要注意的一件事是,當python占用190MB物理內存時,總堆大小僅為14MB。 一旦存儲查詢結果的變量超出范圍,堆概要文件將正確反映垃圾回收:
Partition of a set of 83586 objects. Total size = 6437744 bytes.
Index Count % Size % Cumulative % Kind (class / dict of class)
0 44928 54 3316108 52 3316108 52 str
但是,內存占用量保持不變:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
8225 root 16 0 195m 192m 3432 S 0.0 11.3 0:13.46 python
...
為什么python的物理內存占用量和python堆的大小之間會有如此大的差異?
Python從C堆分配Unicode對象。 因此,當您分配它們中的許多(連同其他malloc塊),然后釋放除最后一個塊之外的大多數塊時,C malloc不會將任何內存返回給操作系統,因為C堆只會在最后收縮(不在中間)。 釋放最后一個Unicode對象將在C堆的末尾釋放該塊,然后允許malloc將其全部返回給系統。
除了這些問題之外,Python還維護了一組釋放的unicode對象,以加快分配速度。 因此,當釋放最后一個Unicode對象時,它不會立即返回到malloc,從而使所有其他頁面都卡住了。
CPython實現僅異常釋放分配的內存。 這是一個廣為人知的錯誤,但CPython開發人員並未對此給予太多關注。 建議的解決方法是“分叉”消耗大量RAM的進程。
您正在使用哪個版本的python?
我問是因為較舊的CPython版本沒有釋放內存,並且在Python 2.5中已修復。
我已經實現了赫魯斯克的“死而復生”的建議。 我正在使用os.fork()在子進程中執行代碼的內存密集型部分,然后讓子進程退出。 父進程在子進程上執行os.waitpid(),以便在給定時間僅執行一個線程。
如果有人發現此解決方案有任何陷阱,請發出提示。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.