Python的內(nèi)存管理機(jī)制可以從三個(gè)方面來講:
- 引用計(jì)數(shù)
- 垃圾回收
- 內(nèi)存池機(jī)制
引用計(jì)數(shù)
Python采用了類似Windows內(nèi)核對象一樣的方式來對內(nèi)存進(jìn)行管理训裆。每一個(gè)對象,都維護(hù)這一個(gè)對指向該對對象的引用的計(jì)數(shù)尚镰。
引用計(jì)數(shù)加1:
1.對象被創(chuàng)建:x=4
2.另外的變量被創(chuàng)建:y=x
3.被作為參數(shù)傳遞給函數(shù):foo(x)
4.作為容器對象的一個(gè)元素:a=[1,x,'33']
引用計(jì)數(shù)減少:
1.一個(gè)本地引用離開了它的作用域。比如上面的foo(x)函數(shù)結(jié)束時(shí),x指向的對象引用減1。
2.對象的別名被顯式的銷毀:del x
3.對象的一個(gè)別名被賦值給其他對象:x=123
4.對象從一個(gè)窗口對象中移除:myList.remove(x)
5.窗口對象本身被銷毀:del myList璧南,或者窗口對象本身離開了作用域。
垃圾回收
1师逸、當(dāng)內(nèi)存中有不再使用的部分時(shí)司倚,垃圾收集器就會(huì)把他們清理掉。它會(huì)去檢查那些引用計(jì)數(shù)為0的對象篓像,然后清除其在內(nèi)存的空間动知。當(dāng)然除了引用計(jì)數(shù)為0的會(huì)被清除,還有一種情況也會(huì)被垃圾收集器清掉:當(dāng)兩個(gè)對象相互引用時(shí)员辩,他們本身其他的引用已經(jīng)為0了盒粮。
2、垃圾回收機(jī)制還有一個(gè)循環(huán)垃圾回收器, 確保釋放循環(huán)引用對象(a引用b, b引用a, 導(dǎo)致其引用計(jì)數(shù)永遠(yuǎn)不為0)奠滑。
內(nèi)存池機(jī)制
Python的內(nèi)存機(jī)制以金字塔行丹皱,-1,-2層主要有操作系統(tǒng)進(jìn)行操作宋税,
第0層是C中的malloc摊崭,free等內(nèi)存分配和釋放函數(shù)進(jìn)行操作;
第1層和第2層是內(nèi)存池杰赛,有Python的接口函數(shù)PyMem_Malloc函數(shù)實(shí)現(xiàn)呢簸,當(dāng)對象小于256K時(shí)有該層直接分配內(nèi)存;
第3層是最上層淆攻,也就是我們對Python對象的直接操作阔墩;
Python提供了對內(nèi)存的垃圾收集機(jī)制,但是它將不用的內(nèi)存放到內(nèi)存池而不是返回給操作系統(tǒng)瓶珊。
正如上面提到的啸箫,Python中所有小于256個(gè)字節(jié)的對象都使用pymalloc實(shí)現(xiàn)的分配器(這里還是會(huì)調(diào)用 malloc 分配內(nèi)存,但每次會(huì)分配一塊大小為256k的大塊內(nèi)存.),而大的對象則使用系統(tǒng)的 malloc伞芹。另外Python對象忘苛,如整數(shù),浮點(diǎn)數(shù)和List唱较,都有其獨(dú)立的私有內(nèi)存池扎唾,對象間不共享他們的內(nèi)存池。也就是說如果你分配又釋放了大量的整數(shù)南缓,用于緩存這些整數(shù)的內(nèi)存就不能再分配給浮點(diǎn)數(shù)胸遇。經(jīng)由內(nèi)存池登記的內(nèi)存到最后還是會(huì)回收到內(nèi)存池,并不會(huì)調(diào)用 C 的 free 釋放掉.以便下次使用.對于簡單的Python對象,例如數(shù)值汉形、字符串纸镊,元組(tuple不允許被更改)采用的是復(fù)制的方式(深拷貝?)倍阐,也就是說當(dāng)將另一個(gè)變量B賦值給變量A時(shí),雖然A和B的內(nèi)存空間仍然相同逗威,但當(dāng)A的值發(fā)生變化時(shí)峰搪,會(huì)重新給A分配空間,A和B的地址變得不再相同凯旭。
注:在Python中概耻,許多時(shí)候申請的內(nèi)存都是小塊的內(nèi)存,這些小塊內(nèi)存在申請后罐呼,很快又會(huì)被釋放鞠柄,由于這些內(nèi)存的申請并不是為了創(chuàng)建對象,所以并沒有對象一級的內(nèi)存池機(jī)制嫉柴。這就意味著Python在運(yùn)行期間會(huì)大量地執(zhí)行malloc和free的操作春锋,頻繁地在用戶態(tài)和核心態(tài)之間進(jìn)行切換,這將嚴(yán)重影響 Python的執(zhí)行效率差凹。為了加速Python的執(zhí)行效率,Python引入了一個(gè)內(nèi)存池機(jī)制侧馅,用于管理對小塊內(nèi)存的申請和釋放危尿。這也就是之前提到的 Pymalloc機(jī)制。
接著馁痴,我們繼續(xù)談python內(nèi)存情況谊娇,在面試過程中被問到
python中的list在內(nèi)存中是以數(shù)組方式存儲(chǔ)還是鏈表的方式呢?罗晕?济欢?
通過查閱一些資料,發(fā)現(xiàn)list的存儲(chǔ)方式是arraylist(動(dòng)態(tài)數(shù)組)小渊,與它相對應(yīng)的是linkedlist(鏈表)法褥,arraylist其實(shí)就是數(shù)組了,其實(shí)就相當(dāng)于C++中的vector酬屉,只不過這時(shí)的list可以存儲(chǔ)不同類型的元素半等。那么我們明白了這些后,使用的時(shí)候才會(huì)更加注意對于插入或者刪除頻繁的時(shí)候呐萨,list效率是比較低的杀饵,畢竟它存儲(chǔ)形式是arraylist。
python中的tuple存儲(chǔ)形式是什么呢谬擦?
tuple在內(nèi)存中的存儲(chǔ)形式就是常量數(shù)組切距,因?yàn)樗遣豢勺兊臄?shù)據(jù)類型,所以常量數(shù)組估計(jì)大家都能理解惨远。
python中的dictionary存儲(chǔ)形式是什么呢谜悟?
字典相當(dāng)于C++標(biāo)準(zhǔn)庫中的map
字符串呢
字符串其實(shí)就是不能修改的list话肖,也是數(shù)組的形式,這和c/c++是一致的赌躺。
參考文章:
http://hackerxu.com/2015/01/13/ram.html
http://blog.csdn.net/zhangweijiqn/article/details/39235169