什么是垃圾回收
垃圾回收是指在程序運行過程中,通過某種機制刪除不再需要使用的對象,釋放其使用的內存資源。
為什么需要垃圾回收
- 內存資源有限且珍貴,如果資源不再使用了,應當盡早把其占用的內存空間騰出來。
- 若程序編寫不當,使用內存資源時僅申請而不釋放,會造成“內存泄漏”,現(xiàn)象是程序占用的內存不斷增加。
- 編程語言如果提供了自動的垃圾回收機制,開發(fā)者在開發(fā)過程中能夠適當減少對內存申請、釋放的關注,把更多的精力投入業(yè)務邏輯的開發(fā)中。
Python語言如何進行垃圾回收
- 引用計數(shù)法(Reference Counting)
- 追蹤法 / 標記刪除法(Tracing / Mark and Sweep)
- 分代回收(基于弱代假設)
什么是引用計數(shù)法
存儲對象時,除了存儲對象的類型和值外,同時還存儲一個計數(shù)器其被引用的次數(shù),在對象被引用時該計數(shù)器遞增一,在對象的某一引用關系被解除后,該計數(shù)器的值遞減一,一旦對象的引用計數(shù)遞減為零,則刪除該對象,釋放其占用的內存空間。
什么時候引用計數(shù)遞增一
- 對象被創(chuàng)建時
- 對象被添加都容器中時
- 對象被作為參數(shù)傳遞到函數(shù)中時
什么時候引用計數(shù)遞減一
- 顯示使用del語句刪除對象時
- 對象被移出容器時
- 函數(shù)參數(shù)或局部變量在函數(shù)調用結束時
引用計數(shù)法的優(yōu)點
- 實現(xiàn)簡單
- 實時生效,對象的引用計數(shù)一旦遞減為零,立刻就被回收
- 垃圾回收的操作被分散在程序運行的整個過程中
引用計數(shù)法的缺點
- 對所有對象都引入了一個額外的計數(shù)變量,程序有了額外的開銷
- 程序運行中需要不斷對所有對象的引用計數(shù)進行遞增、遞減的操作
- 并發(fā)訪問計數(shù)變量時可能會發(fā)生錯誤,因此非線程安全的,Python語言為了解決這個問題引入了GIL(Global Interpreter Lock)
- 無法回收不再使用的但是存在循環(huán)引用的對象
什么是追蹤法 / 標記刪除法
指從“GC根節(jié)點”出發(fā),通過引用關系追蹤找出所有“可達”的對象,標記出存活的對象(即可達的對象),刪除所有已死的對象(即不可達的對象),在內存中的對象數(shù)量超過特定閾值后,會啟動該回收機制。
追蹤法/標記刪除法的優(yōu)點
- 解決了存在循環(huán)引用的對象的回收問題
追蹤法/標記刪除法的缺點
- 無法實時觸發(fā),只能定時或在對象達到某一閾值后執(zhí)行垃圾回收
- 如果對象很多,垃圾回收對性能可能有較大的損耗
什么是分代回收
分代回收是一種追蹤法垃圾回收的一種,基于“大多數(shù)對象在年輕的時候就會被回收”的假設(類似已經(jīng)流傳了更多年的書籍比新出版的書籍更可能繼續(xù)流傳下去),對“年輕”的對象進行更高頻率的垃圾回收。
- Python將對象分為0、1、2代,分別使用三個列表進行記錄。
- 新創(chuàng)建出來的對象會被存放到0代列表
- 當某一代對象觸發(fā)垃圾回收時,比該代小的代也會被進行垃圾回收(因此“年輕”的對象被更高頻地檢測回收)
- 在一次垃圾回收中存活下來的對象會被移入下一代,直到最大的2代。
什么時候觸發(fā)
- 垃圾回收算法會在列表內的對象數(shù)目超過特定的閾值后執(zhí)行
分代回收的優(yōu)點
- 解決了標記刪除法每次進行垃圾回收時針對所有對象進行垃圾回收可能導致較大的性能損耗的問題