天天看點

如何解決Python2的記憶體洩漏問題

python程序記憶體撐大了下不去,隻能手動重新開機釋放記憶體,這麼坑爹的事情你遇到過嗎?哪家記憶體配置設定器強?結果一目了然。

線上程序目前都是使用原生的Python記憶體配置設定器(pymalloc),在正常的情況下表現還算穩定,但如果來了一波類似于武神壇或者天下第一的比武大會,為手機瞬間帶來了10倍于平時的流量,一陣狂虐之後,Python程序占用的記憶體被撐大就下不去了。關于Python的記憶體不釋放問題,可以參考一下這兩篇文章:python記憶體不釋放原理,Python memory management and TCMalloc。

為了解決記憶體洩漏的問題,我專門使用了三種編譯方式去編譯Python2.7解釋器

以下分别使用pymalloc、without-pymalloc、tcmalloc測試1千萬個object的list記憶體釋放情況(注:預設使用Python2.7)。

  • 測試環境
CPU 4 QEMU Virtual CPU version 2.1.0
記憶體 15G
作業系統核心 Linux onlinegame-229-88 3.2.0-4-amd64 #1 SMP Debian 3.2.60-1+deb7u1 x86_64 GNU/Linux
  • 測試代碼
#!/usr/bin/env python
# coding: utf-8
import os
import gc
import time

class Test:
    def __init__(self):
        self.name = "haha"

def run():
    L = []
    begin = time.time()
    for i in xrange():
        L.append(Test())
    end = time.time()
    print 'cost:%s' %(round(end-begin,))
    input_str = raw_input('\nrun: ')
if __name__=="__main__":
    print "pid:%s" %os.getpid()
    input_str = raw_input('\nstart')
    run()
    input_str = raw_input('\nready to collect')
    gc.collect()
    input_str = raw_input('\ncollected.')
           
  • 測試結果
\ pymalloc without-pymalloc tcmalloc
list對象數量 10000000 10000000 10000000
平均消耗時間 21.379s 21.199s 20.53s
run調用期間記憶體占用 3.6g 3.6g 3.6g
run結束後記憶體占用 2.7g 23m 8224b
collect後的記憶體占用 2.7g 23m 8224b
  • 結論

    pymalloc在一輪暴虐之後程序記憶體下不去。

    不使用pymalloc容易導緻不少相容性的問題出現,而且許多python的新feature會用不了,不建議這麼做。

    而tcmalloc果然名不虛傳,run方法結束後,記憶體馬上釋放到解放前。建議生産環境嘗試使用tcmalloc編譯的Python解釋器,其它相容性的問題有待考證。