2010年8月17日 星期二

Python 強迫釋放記憶體的解法

悲劇發生的情境:
你寫了個 python 程式, 它先做些事吃掉個 10G 記憶體, 但隨後用不到這 10G。然後它 fork 成 4 個 processes 處理一些事。結果用 htop 一看, 發現有 4 + 1 個 processes 各吃掉 10G 記憶體。幸好 Linux  有用 copy-on-write, 所以系統顯示總共只用掉 10G。但在 5 個 processes 忙碌做事的途中, 別人的程式也在搶記憶體, 造成 OS 判斷錯誤把這幾個 processes 之一搬到 swap (或是誤把別人搬到 swap), 結果整個系統噴了, 大家都慢到做不完事。
解法見《How can I explicitly free memory in Python?》, 結論是無法強迫 python 釋放記憶體, 別再相信 gc.collect() 有效這類不實謠言, 至少我試了沒有效。只好用最根本的解法, fork 一個 subprocess 讓它去做那吃掉 10G 的事, 做完掛掉後, OS 自然會回收那 10G, 就和大自然生生不息的循環一樣。由於一開始執行的 process 本身沒吃掉任何記憶體, 之後 fork 4 個 processes 自然沒有占記憶體的問題。

聽起來頗麻煩的, 好消息是, 自 python 2.6 版起有了 multiprocessing, 2.4 和 2.5 版也有 backport, 只要改用 multiprocessing 執行原來吃記憶體的函式即可。若需要讀函式的回傳值, 參考這裡的說明, 即可搞定。

沒有留言:

張貼留言

在 Fedora 下裝 id-utils

Fedora 似乎因為執行檔撞名,而沒有提供 id-utils 的套件 ,但這是使用 gj 的必要套件,只好自己編。從官網抓好 tarball ,解開來編譯 (./configure && make)就是了。 但編譯後會遇到錯誤: ./stdio.h:10...