我知道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保持這種內存分配?
所以我已經通讀了你的牆上的文字,我正在努力尋找問題......你究竟在問什麼?你說python不釋放內存,但python3k確實......你在找什麼?你能否簡明扼要地回答問題? – mgilson
我以最短的方式添加了我能想到的問題:) – resi
@resi我們是pythonista。你能以單線形式提出這個問題嗎?我能理解的是,爲什麼python 2沒有釋放內存。 – thefourtheye