標籤:記憶體 映像 ruby bsp 如何 程式 通過 自動 col
python屬於動態語言,我們可以隨意的建立和銷毀變數,那麼如果頻繁的建立和銷毀則會浪費cpu,那麼python內部是如何最佳化的呢?
python和其他很多進階語言一樣,都內建記憶體回收機制,不用我們去維護,也避免了出現記憶體流失,懸null 指標等bug,那麼python內部如何進行記憶體回收的呢?
python的記憶體回收,我們用gc模組去開啟或者關閉它,那麼gc模組又是什麼呢?
python的最佳化機制
記憶體回收
關於循環參考進行一個測試
import gc # python的一個記憶體回收模組,garbage collectionclass A(object): def __init__(self): passdef foo(): while True: a1 = A() a2 = A() a1.t = a2 a2.t = a1 del a1 del a2gc.disable()foo()‘‘‘當我們使用gc.disable(),就意味著我們把python的記憶體回收機制給關閉了,那麼一些垃圾便不會被自動回收。首先我們建立了兩個執行個體對象a1和a2,然後在a1的內部建立一個屬性指向a2,在a2的內部建立一個屬性指向a1那麼a1和a2的引用計數都為2,即使del a1,del a2,它們的引用計數還是為1,因此仍然會待在記憶體裡不會被回收當我們進行第二輪迴圈的時候,會繼續再記憶體中建立一份a1和a2,不斷地迴圈會發現程式所使用的記憶體也來越大,直至溢出崩潰‘‘‘
探討一下ruby和python的記憶體回收機制
ruby和python均屬於指令碼語言,它們是非常相似的,比方說定義兩個類
ruby的對象分配
當我們執行上面的Node.new(1)時,ruby在內部給我們做了什嗎?ruby是如何建立新的對象的呢?其實ruby做的很少,實際上早在代碼執行之前,ruby就建立了成百上千個對象(類似於python的小整數對象池),並把它們串在鏈表上,叫做可用鏈表
因此在建立對象的時候直接拿來用就可以了。
白色的小方格相當於標著一個“未使用預建立對象”,當我們調用Node.new方法時,ruby直接取出一個給我們使用即可
可以簡單地理解,黑色格子是當前使用的對象,白色格子是未使用對象。當我們建立了一個“ABC”,放在了第一個格子的位置,讓n1這個變數指向它。
由於這是一個鏈表,鏈表上的對象一般儲存著下一個對象的記憶體指標,因此我們只需要找到一個便可以順藤摸瓜將剩下的全給找出來,由於已經被使用,那麼“箭頭”也被切斷了,剩下的白色格子在一個鏈表上,儲存的是可用的記憶體
如果我們再次調用Node.new,ruby將繼續遞給我們一個對象。
因此隨著我們不斷地建立,ruby不斷的從可用鏈表裡取預建立對象給我們,從而也就導致了可用鏈表會越來越短
注意映像,我為n1不止賦了一次值,賦完值之後,又給n1賦了新的值,讓n1指向了新的記憶體空間,那麼就會有垃圾產生。
ruby的標記--清除
當我們把可用空間全部用完了,可用鏈表上變得空空如也
可以看到所有格子都變灰了,沒有白格子了。那麼ruby是如何解決這一問題的呢?
ruby使用的是標記--清除,首先ruby會把程式停下來,然後輪詢所有的指標,變數和代碼產生的別的引用對象以及其他值,同時ruby通過自身的虛擬機器遍曆內部指標,只要對象被引用,那麼便將其標記(mark)出來。
只要沒有被標記的,那麼便是垃圾。
ruby將這些沒有被標記的垃圾進行回收,並把它們送回到可用鏈表當中。
由於內部發生的很快,ruby不會將對象到處拷貝,而是通過調整內部的指標,將其指向一個新鏈表的方式,來將垃圾對象歸位到可用鏈表當中的。
python的對象分配
的的
python的最佳化機制與記憶體回收與gc模組