2013-12-17 73 views
3

我知道python有自己的內存管理實現使用areans爲不同大小的對象和更多,雖然我還沒有找到一個徹底的文檔。 但我想了解發生了什麼。python2是否不願釋放內存?

背景是一個長期運行的python2數據庫應用程序,它以某種方式出現泄漏內存,它運行在64位linux上。 這個應用程序每天都會從數據庫讀取一些數據,爲了讀取這些行(使用MySQLdb),它總計大約有3.5GB的RAM使用量。大約有350萬行,之後減少到100行,剩下的行數超出範圍(「釋放」)。

但python-2.7只釋放了現在「未使用」內存的一小部分。我很期待內存被重用,但我觀察到,這種內存似乎「緩慢泄漏」。所提到的數據庫應用程序每天都會讀取這些大量的數據。連續讀取兩次(或更多次)只爲第一次讀取分配內存,然後顯然重新使用此內存。但讓它運行幾個小時然後再讀取DB數據會產生下一個3 + GB的內存分配高峯(它永遠不會被釋放)。

要添加更多背景(並且讓事情更糟糕來解釋)我不得不說,這個數據庫應用程序不是空閒的,而是永久執行任務。我非常肯定從監視內存使用情況(nagios性能數據),如果沒有這個特定的數據庫查詢,內存使用率永遠不會攀升到3.5GB RAM(甚至是關閉)。但啓用此查詢後,每天都會添加3 GB的RAM。 有問題的查詢返回大多數唯一的整數和浮點數。

這是我開始懷疑python的主要原因。我覺得我已經閱讀了大量的信息,看着_PyObject_DebugMallocStats(),但不知道Python決定保留幾千兆字節(或爲什麼)。

它歸結爲一個很簡單的例子(未表示關於數據的真實生活狀況,我知道的xrange()):

def mem_usage(pid=None): 
    mem = 0 
    proc = str(pid or "self") 
    with open("/proc/%s/smaps" % proc) as fstat: 
     for l in fstat: 
      if not l.startswith("Private_"): 
       continue 
      mem += int(l.split(":", 1)[1].strip().split(" ", 1)[0]) 
    return mem 

mem_usage()     # reports a few MB 
x = list(range(100000000)) # use list() for py3k 
mem_usage()     # reports ~3GB 
del x 
mem_usage()     # reports ~2.5GB 

請告訴我有趣的是py3k釋放當我刪除了巨大的內存名單。不僅僅是一小部分,而且幾乎所有的內存使用量都只比開始時略高。

我已經調查了memory_profiler(我想它沒有做任何遠遠超過給定的mem_usage()函數)沒有任何洞察力。我已經閱讀了關於gdb-heap的文章,但是到目前爲止還無法實現。

我實際上不相信有解決方案(除了重新啓動應用程序或減少從數據庫讀取的數據量)。但我真的很感謝這個話題的任何見解。

編輯:

總結我的問題:爲什麼蟒蛇-2.7保持這種內存分配?

+1

所以我已經通讀了你的牆上的文字,我正在努力尋找問題......你究竟在問什麼?你說python不釋放內存,但python3k確實......你在找什麼?你能否簡明扼要地回答問題? – mgilson

+0

我以最短的方式添加了我能想到的問題:) – resi

+0

@resi我們是pythonista。你能以單線形式提出這個問題嗎?我能理解的是,爲什麼python 2沒有釋放內存。 – thefourtheye

回答

2

range例如保持一噸的內存周圍因爲Python 2.7從不釋放int S:

block_list is a singly-linked list of all PyIntBlocks ever allocated, linked via their next members. PyIntBlocks are never returned to the system before shutdown (PyInt_Fini).

但是,這不應該是一個問題,除非在某些時候,數千兆字節ints同時還活着。否則,Python將使用舊的丟棄整數來表示您使用的任何新的整數。如果你的有幾個千兆字節的實時價值,我建議找一種方法來保持少一些。

+0

我發現PyIntBlocks的問題是由於同時存在大量的int對象造成的(並且與float相同)。我不確定我是否正在讀取intobject.c,但是僞釋放的塊被收集在free_list中並在以後重用,這是真的嗎? 這是否意味着我的數據庫應用程序在第二天再次運行時(當它在mem使用中執行另一次跳躍時)會用完所有PyIntBlocks? – resi

+0

我不相信在Python 2.7中處理整數和浮點數是我在這裏唯一的問題,但無法獲得更多的見解。不過,你指出了,所以我認爲接受你的答案是公平的。 – resi