標籤:兩種 assert utf-8 差值 狀態 服務 www 引用 htm
Python 的記憶體管理是自動的。Python 使用引用計數和記憶體回收來管理記憶體。
引用計數:每個對象有一個引用它的對象數目。引用計數為 0 的對象被視作垃圾。當一個引用它的對象建立時,引用計數加一,當一個引用它的對象銷毀時,引用計數減一。
引用計數有一些缺點,其中一個是它不能處理循環參考。
def make_cycle(): 1 = [ ] 1.append(l)make_cycle()
因為 make_cycle() 中建立了一個循環參考對象,所以當函數返回後,它並不會被引用計數回收。
自動回收引用對象
因為循環參考需要消耗計算資源來發現,所以記憶體回收是一個預先安排好的任務。Python 基於指派至與回收對象的差值來安排記憶體回收。當分配數目減去回收數目大於臨界值時,觸發記憶體回收。可以通過 gc 模組來查看記憶體回收的臨界值:
import gcgc.get_threshold()(700, 10, 10)
我們可以看到,預設的臨界值時 700。
當你的 Python 程式耗盡了記憶體後,自動記憶體回收不會運行。你的程式會拋出異常,這個異常必須被處理,否則你的程式會崩潰。這是由於自動記憶體回收是基於對象的數目而不是基於對象的大小。因此可以考慮在佔據大量記憶體的代碼後手動運行記憶體回收。
手動記憶體回收
對於一些程式,尤其是長時間啟動並執行服務端程式或者嵌入式程式,自動記憶體回收可能不足。
手動執行記憶體回收:
import gc# 返回它回收的對象數目gc.collect()
如果我們建立一些循環參考,我們可以看到手動回收生效了:
# -*- coding: utf-8 -*-import gcdef _make_cycle(): l = {} l[0] = ldef make_cycle(num=1): for i in range(num): _make_cycle()# 先清理乾淨gc.collect()assert gc.collect() == 0make_cycle(10)assert gc.collect() == 10
通常,有兩種手動回收的策略:
- 基於時間。定時調用記憶體回收。
- 基於事件。在一個事件中調用記憶體回收。比如當一個使用者與伺服器中斷連線或者知道應用要進入停頓狀態後。
推薦行為
儘可能在需要的時候調用記憶體回收來避免對重要程式造成效能影響。記憶體回收應該是設計 Python 應用的一部分。
- 不要隨意運行記憶體回收,因為它需要消耗很多計算資源來計算每個記憶體對象
- 在你的應用完全啟動並進入平穩運行狀態後再運行記憶體回收。這可能可以釋放大量用於開啟、解析檔案、編輯、修改對象後者不會再用到的模組的記憶體
- 在運行不常用代碼後運行記憶體回收。比如,在一個一天一次的解析、匯出資料的任務後運行記憶體回收
- 在對時間要求高的任務前後運行記憶體回收來阻止可能的記憶體回收分走已耗用時間
參考
- https://www.digi.com/resources/documentation/digidocs/90001537/references/r_python_garbage_coll.htm
Python 記憶體回收