python 內(nèi)存分配和垃圾回收

內(nèi)存分配

Python中的內(nèi)存管理機(jī)制的層次結(jié)構(gòu)提供了4層


最底層則是C運(yùn)行的malloc和free接口

第一層則是在第0層的基礎(chǔ)之上對(duì)其提供的接口進(jìn)行了統(tǒng)一的封裝笤闯,這是因?yàn)殡m然不同的操作系統(tǒng)都提供標(biāo)準(zhǔn)定義的內(nèi)存管理接口望蜡,但是對(duì)于某些特殊的情況不同的操作系統(tǒng)都不同的行為,比如說(shuō)調(diào)用malloc(0)棕孙,有的操作系統(tǒng)會(huì)返回NULL舔亭,表示內(nèi)存申請(qǐng)失斝┡颉;然而有的操作系統(tǒng)會(huì)返回一個(gè)貌似正常的指針钦铺,但是這個(gè)指針?biāo)傅膬?nèi)存并不是有效的订雾。為了廣泛的移植性,Python必須保證相同的語(yǔ)義一定代表相同的運(yùn)行行為职抡。

在第二層內(nèi)存管理機(jī)制上葬燎,Python構(gòu)建了更高抽象的內(nèi)存管理策略,比如說(shuō)一些常用對(duì)象缚甩,包括整數(shù)對(duì)象谱净、字符串對(duì)象等等。

第三層主要是對(duì)象緩沖池機(jī)制擅威,它基于在第二層的內(nèi)存池壕探。

內(nèi)存池

Python為了避免頻繁的申請(qǐng)和刪除內(nèi)存所造成系統(tǒng)切換于用戶態(tài)和核心態(tài)的開(kāi)銷,從而引入了內(nèi)存池機(jī)制郊丛,專門(mén)用來(lái)管理小內(nèi)存的申請(qǐng)和釋放李请。整個(gè)小塊內(nèi)存的內(nèi)存池可以視為一個(gè)層次結(jié)構(gòu),其一共分為4層厉熟,從下之上分別是block导盅、pool、arena和內(nèi)存池揍瑟。需要說(shuō)明的是:block白翻、pool和area都是代碼中可以找到的實(shí)體,而最頂層的內(nèi)存池只是一個(gè)概念上的東西绢片,表示Python對(duì)于整個(gè)小塊內(nèi)存分配和釋放行為的內(nèi)存管理機(jī)制滤馍。

內(nèi)存大小以256字節(jié)為界限,大于則通過(guò)malloc進(jìn)行分配底循,小于則通過(guò)內(nèi)存池分配巢株。


內(nèi)存池

block:最小的內(nèi)存單元,大小為8的整數(shù)倍熙涤。有很多種類的block阁苞,不同種類的block都有不同的內(nèi)存大小,申請(qǐng)內(nèi)存的時(shí)候只需要找到適合自身大小的block即可祠挫,當(dāng)然申請(qǐng)的內(nèi)存也是存在一個(gè)上限猬错,如果超過(guò)這個(gè)上限,則退化到使用最底層的malloc進(jìn)行申請(qǐng)茸歧。

pool:一個(gè)pool管理著一堆有固定大小的內(nèi)存塊倦炒,其大小通常為一個(gè)系統(tǒng)內(nèi)存頁(yè)的大小。

arena:多個(gè)pool組合成一個(gè)arena软瞎。

GC

引用計(jì)數(shù)

python里每一個(gè)東西都是對(duì)象逢唤,它們的核心就是一個(gè)結(jié)構(gòu)體:

typedef struct_object {?

?????int ob_refcnt;?

?????struct_typeobject *ob_type;

} PyObject;

PyObject,是每個(gè)對(duì)象必有的內(nèi)容拉讯,其中ob_refcnt就是做為引用計(jì)數(shù),引用計(jì)數(shù)為0時(shí),該對(duì)象生命就結(jié)束了鳖藕。

導(dǎo)致引用計(jì)數(shù)+1的情況

對(duì)象被創(chuàng)建魔慷,例如a=23

對(duì)象被引用,例如b=a

對(duì)象被作為參數(shù)著恩,傳入到一個(gè)函數(shù)中院尔,例如func(a)

對(duì)象作為一個(gè)元素,存儲(chǔ)在容器中喉誊,例如list1=[a,a]

導(dǎo)致引用計(jì)數(shù)-1的情況

對(duì)象的別名被顯式銷毀邀摆,例如del a

對(duì)象的別名被賦予新的對(duì)象,例如a=24

一個(gè)對(duì)象離開(kāi)它的作用域伍茄,例如f函數(shù)執(zhí)行完畢時(shí)栋盹,func函數(shù)中的局部變量(全局變量不會(huì))

對(duì)象所在的容器被銷毀,或從容器中刪除對(duì)象

優(yōu)點(diǎn):

實(shí)時(shí)性:一旦沒(méi)有引用敷矫,內(nèi)存就直接釋放了例获。不用像其他機(jī)制等到特定時(shí)機(jī)。實(shí)時(shí)性還帶來(lái)一個(gè)好處:處理回收內(nèi)存的時(shí)間分?jǐn)偟搅似綍r(shí)曹仗。

缺點(diǎn):

維護(hù)引用計(jì)數(shù)消耗資源

循環(huán)引用

標(biāo)記清除

標(biāo)記-清除只關(guān)注那些可能會(huì)產(chǎn)生循環(huán)引用的對(duì)象榨汤,顯然,像是PyIntObject怎茫、PyStringObject這些不可變對(duì)象是不可能產(chǎn)生循環(huán)引用的件余,因?yàn)樗鼈儍?nèi)部不可能持有其它對(duì)象的引用。Python中的循環(huán)引用總是發(fā)生在container對(duì)象之間遭居,也就是能夠在內(nèi)部持有其它對(duì)象的對(duì)象,比如list旬渠、dict俱萍、class等等

原理:1. 尋找跟對(duì)象(root object)的集合作為垃圾檢測(cè)動(dòng)作的起點(diǎn),跟對(duì)象也就是一些全局引用和函數(shù)棧中的引用告丢,這些引用所指向的對(duì)象是不可被刪除的枪蘑;2. 從root object集合出發(fā),沿著root object集合中的每一個(gè)引用岖免,如果能夠到達(dá)某個(gè)對(duì)象岳颇,則說(shuō)明這個(gè)對(duì)象是可達(dá)的,那么就不會(huì)被刪除颅湘,這個(gè)過(guò)程就是垃圾檢測(cè)階段话侧;3. 當(dāng)檢測(cè)階段結(jié)束以后,所有的對(duì)象就分成可達(dá)和不可達(dá)兩部分闯参,所有的可達(dá)對(duì)象都進(jìn)行保留瞻鹏,其它的不可達(dá)對(duì)象所占用的內(nèi)存將會(huì)被回收悲立,這就是垃圾回收階段。(底層采用的是鏈表將這些集合的對(duì)象連接在一起)

分代回收

將系統(tǒng)中的所有內(nèi)存塊根據(jù)其存活時(shí)間劃分為不同的集合新博,每一個(gè)集合就成為一個(gè)“代”薪夕,Python默認(rèn)定義了三代對(duì)象集合,垃圾收集的頻率隨著“代”的存活時(shí)間的增大而減小赫悄。也就是說(shuō)原献,活得越長(zhǎng)的對(duì)象,就越不可能是垃圾埂淮,就應(yīng)該減少對(duì)它的垃圾收集頻率姑隅。那么如何來(lái)衡量這個(gè)存活時(shí)間:通常是利用幾次垃圾收集動(dòng)作來(lái)衡量,如果一個(gè)對(duì)象經(jīng)過(guò)的垃圾收集次數(shù)越多同诫,可以得出:該對(duì)象存活時(shí)間就越長(zhǎng)粤策。



import gc模塊,并且is_enable()=True才會(huì)啟動(dòng)自動(dòng)垃圾回收误窖。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末叮盘,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子霹俺,更是在濱河造成了極大的恐慌柔吼,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,451評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件丙唧,死亡現(xiàn)場(chǎng)離奇詭異愈魏,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)想际,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)培漏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人胡本,你說(shuō)我怎么就攤上這事牌柄。” “怎么了侧甫?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,782評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵珊佣,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我披粟,道長(zhǎng)咒锻,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,709評(píng)論 1 294
  • 正文 為了忘掉前任守屉,我火速辦了婚禮惑艇,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘拇泛。我一直安慰自己敦捧,他們只是感情好须板,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,733評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著兢卵,像睡著了一般习瑰。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上秽荤,一...
    開(kāi)封第一講書(shū)人閱讀 51,578評(píng)論 1 305
  • 那天甜奄,我揣著相機(jī)與錄音,去河邊找鬼窃款。 笑死课兄,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的晨继。 我是一名探鬼主播烟阐,決...
    沈念sama閱讀 40,320評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼紊扬!你這毒婦竟也來(lái)了蜒茄?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,241評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤餐屎,失蹤者是張志新(化名)和其女友劉穎檀葛,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體腹缩,經(jīng)...
    沈念sama閱讀 45,686評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡屿聋,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,878評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了藏鹊。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片润讥。...
    茶點(diǎn)故事閱讀 39,992評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖盘寡,靈堂內(nèi)的尸體忽然破棺而出楚殿,到底是詐尸還是另有隱情,我是刑警寧澤宴抚,帶...
    沈念sama閱讀 35,715評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站甫煞,受9級(jí)特大地震影響菇曲,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜抚吠,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,336評(píng)論 3 330
  • 文/蒙蒙 一常潮、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧楷力,春花似錦喊式、人聲如沸孵户。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,912評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)夏哭。三九已至,卻和暖如春献联,著一層夾襖步出監(jiān)牢的瞬間竖配,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,040評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工里逆, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留进胯,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,173評(píng)論 3 370
  • 正文 我出身青樓原押,卻偏偏與公主長(zhǎng)得像胁镐,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子诸衔,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,947評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容