2013-12-10 115 views

回答

16

禁用垃圾收集器的一種用法是在定時執行代碼時獲得更一致的結果。 The timeit module這樣做。

def timeit(self, number=default_number): 
    if itertools: 
     it = itertools.repeat(None, number) 
    else: 
     it = [None] * number 
    gcold = gc.isenabled() 
    gc.disable() 
    ... 

In Python2和至多Python3.2gc.disable()也用來避免a bug caused by garbage collection occurring between fork and exec。該問題似乎已在Python3.3中得到修復,無需致電gc.disable()

3

另一個用例是手動控制垃圾收集gc.collect()

+0

但是,首先要禁用GC才能使用'gc.collect()'?或者'gc.collect()'的用例是什麼? (注意:我實際上在過去的C#應用​​程序中有這樣的用例,它在<512MiB的框中出現內存不足)。 –

+0

不需要。您可以隨時調用''gc.collect()''任何時候AFAIK。 –

6

從您鏈接到同一頁:

由於收集補充了 Python中已經使用引用計數,你如果您確定程序 未創建參考週期,可以禁用收集器。

因此,這回答了問題的第二部分,「如果沒有它,如何有效地管理內存」。不要創建參考週期。當然,這是一個相當有限的用例。

對於問題的第一部分,答案就是性能。再次,一個相當有限的用例。

禁用GC只有在以下情況下才有所幫助:(a)GC實際上正在進行工作,並且(b)該工作沒有取得任何成果,也就是說找不到任何東西來釋放,或者發現太少以至於認爲程序可以只要禁用GC,就容忍泄漏。因此,如果您的程序速度太慢並且不會創建參考週期並且禁用GC似乎會加快速度,那麼您會考慮禁用GC。

我推測(基於以前的GC,我已經看到,而不是Python的),如果你沒有分配任何內存,那麼垃圾收集器將不會有任何長期的性能成本。它可能有一些短期和不可預測的成本整理以前的成本。所以即使在你要進入一個龐大的數字處理例程,並且認爲你應該考慮從代碼的這一部分中擠出所有可能的性能,禁用GC的同時你仍然不會幫助。它只會延遲整理之前參考週期的時間成本,直到您重新啓用GC爲止。

可以說,短時間運行並且不佔用太多內存的程序不需要垃圾回收,它們可以容忍泄漏。但更可以說,如果你開始這樣想,你最終會遇到一個漏洞超出預期的程序的麻煩。

+0

問題是,在實踐中,確保你沒有參考週期是很困難的(不可能)。你可以很容易地確定你的代碼沒有,但是你的依賴關係呢?由於模塊,函數和類通常不會指定它們是否創建引用循環,因此您必須仔細閱讀每個依賴性和傳遞依賴性(包括標準庫)的代碼,並驗證是否沒有這樣的引用。當然,升級依賴可能會引入一個循環。 – Kevin

+0

@凱文:絕對。我認爲我打算「相當有限」是一個諷刺性的輕描淡寫。 –

5

啓用GC的問題始終是,您不知道它會發生。所以如果你的程序(的一部分)對時間要求很高,需要實時等,那麼你可以在程序運行的那段時間(這部分)禁用GC。

您是否想要稍後再打開自動GC,或者如果您希望通過調用gc.collect()手動執行此操作,則不會涉及該問題。此外,有些程序只能運行很短的時間,因此開發人員可以確保在那段時間內不會出現任何內存問題(請考慮像ls這樣的程序)。那麼整個GC方面可以忽略,而有利於性能。