python和c++的區別以及python回收機制

  1. 語言類型
    python是一種基於解釋器的語言,解釋器會逐行讀取代碼;首先將python編譯成字節碼,然後由C程序解釋.
    C++是一種編譯語言,在其他章節裏寫過,整個過程是編譯器編譯代碼成彙編語言,彙編語言由彙編器生成機器碼,之後還要經過鏈接器載入文件\庫等指令生成可執行代碼,最後裝載器將可執行代碼和數據載入內存,CPU讀取內存執行.

  2. 內存管理
    python由自動垃圾收集器進行內存管理.
    c++中程序員必須自己進行內存管理.

  3. 速度
    python由全局鎖,多線程效果不好
    c++運行效率很高

python 垃圾回收機制

  1. 引用計數
    python的垃圾回收機制主要是引用計數爲主,分代回收爲輔. 引用計數就是每個對象維護一個ob_refcnt,用來記錄當前對象被引用的次數.
    當出現下面的情況時引用+1:
  • 對象被創建 a=1
  • 對象被引用 c=b
  • 對象被當作參數傳入函數中 func(a)
  • 對象被作爲元素存儲在容器中時 List=[a,b] Dict={a:1}

下面四種情況引用減一:

  • 當對象被顯式銷燬 del a
  • 當對象被賦予新的對象 a=2
  • 當對象離開作用域,如func執行完之後,函數內的局部遍歷引用計數器就都會減一
  • 當元素從容器中刪除或者容器被銷燬

當計數器減到0,那麼該內存就會被python虛擬機銷燬.

缺點:

  • 消耗資源,需要維護計數器的資源.
  • 無法解決循環引用的問題,和shared_ptr一樣出現了循環引用無法正常回收
list1=[]
list2=[]
list1.append(list2)
list2.append(list1)

上面的結果是 list1=[[[[[…]]]]] list2=[[[[[…]]]]]

  1. 標記刪除

『標記清除(Mark—Sweep)』算法是一種基於追蹤回收(tracing GC)技術實現的垃圾回收算法。它分爲兩個階段:第一階段是標記階段,GC會把所有的『活動對象』打上標記,第二階段是把那些沒有標記的對象『非活動對象』進行回收。那麼GC又是如何判斷哪些是活動對象哪些是非活動對象的呢?
對象之間通過引用(指針)連在一起,構成一個有向圖,對象構成這個有向圖的節點,而引用關係構成這個有向圖的邊。從根對象(root object)出發,沿着有向邊遍歷對象,可達的(reachable)對象標記爲活動對象,不可達的對象就是要被清除的非活動對象。根對象就是全局變量、調用棧、寄存器。

這個方法就是通過根節點找出可達和不可達的節點組,不可達的節點組就是相互引用或者等待釋放的.
在這裏插入圖片描述

在上圖中,我們把小黑圈視爲全局變量,也就是把它作爲root object,從小黑圈出發,對象1可直達,那麼它將被標記,對象2、3可間接到達也會被標記,而4和5不可達,那麼1、2、3就是活動對象,4和5是非活動對象會被GC回收。

標記清除算法作爲Python的輔助垃圾收集技術主要處理的是一些容器對象,比如list、dict、tuple,instance等,因爲對於字符串、數值對象是不可能造成循環引用問題。

  1. 分代回收

首先建立了一個鏈表,把創建的對象都加入,這個鏈表是Generation Zero.
隨後,Python會循環遍歷零代列表上的每個對象,檢查列表中每個互相引用的對象,根據規則減掉其引用計數。減到0的對象就可以被釋放,不是0的對象就會被移動到一代鏈表中.
循環上面的過程,如果一代鏈表中存活下來的就會被放入二代鏈表.

這個循環遍歷多久執行一次呢? 根據一個GC閾值來判斷,即當分配的計數器計數到某個閾值就開始遍歷.

分代的好處: 保留了長期留存的對象,這些對象就大概率很久纔會被釋放,因此遍歷的頻次可以減少.
這種行爲的理論是弱代假說年親的對象通常死得也快,而老對象則很有可能存活更長的時間。

將系統中的所有內存塊根據其存貨的時間劃分爲不同的集合, 每個集合就成爲一個”代”, 垃圾收集的頻率隨着”代”的存活時間的增大而減小(活得越長的對象, 就越不可能是垃圾, 就應該減少去收集的頻率)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章