Python面試題:Python是如何進(jìn)行內(nèi)存管理的?
一、垃圾回收:
Python不像C++,Java等語言一樣,他們可以不用事先聲明變量類型而直接對(duì)變量進(jìn)行賦值。對(duì)Python語言來講,對(duì)象的類型和內(nèi)存都是在運(yùn)行時(shí)確定的。這也是為什么我們稱Python語言為動(dòng)態(tài)類型的原因(這里我們把動(dòng)態(tài)類型語言可以簡(jiǎn)單的歸結(jié)為對(duì)變量?jī)?nèi)存地址的分配是在運(yùn)行時(shí)自動(dòng)判斷變量類型并對(duì)變量進(jìn)行賦值)。
二、引用計(jì)數(shù):
Python采用了類似windows內(nèi)核對(duì)象一樣的方式來對(duì)內(nèi)存進(jìn)行管理。每一個(gè)對(duì)象,都維護(hù)這一個(gè)對(duì)指向該對(duì)象的引用的計(jì)數(shù)。當(dāng)變量被綁定在一個(gè)對(duì)象上的時(shí)候,該變量的引用計(jì)數(shù)就是1,(還有另外一些情況也會(huì)導(dǎo)致變量引用計(jì)數(shù)的增加),系統(tǒng)會(huì)自動(dòng)維護(hù)這些標(biāo)簽,并定時(shí)掃描,當(dāng)某標(biāo)簽的引用計(jì)數(shù)變?yōu)?的時(shí)候,該對(duì)象就會(huì)被回收。
三、內(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)對(duì)象小于256字節(jié)時(shí)由該層直接分配內(nèi)存;
第三層是最上層,也就是我們對(duì)Python對(duì)象的直接操作;
在C中如果頻繁的調(diào)用malloc與free時(shí),是會(huì)產(chǎn)生性能問題的,在加上頻繁的分配和釋放小塊的內(nèi)存會(huì)產(chǎn)生內(nèi)存碎片。
Python在這里主要干的工作有:
如果請(qǐng)求分配的內(nèi)存在1~256字節(jié)之間就使用自己的內(nèi)存管理系統(tǒng),否則直接使用malloc。
這里還是會(huì)調(diào)用malloc分配內(nèi)存,但每次回分配一塊大小為256字節(jié)的大塊內(nèi)存。
經(jīng)由內(nèi)存池登記的內(nèi)存到最后還是會(huì)回收到內(nèi)存池,并不會(huì)調(diào)用C的free釋放掉,以便下次使用。對(duì)于簡(jiǎn)單的Python對(duì)象,例如數(shù)值、字符串、元組(tuple不允許被更改)采用的是復(fù)制的方式(深拷貝),也就是說當(dāng)講另一個(gè)變量B賦值給變量A時(shí),雖然A和B的內(nèi)存空間仍然相同,但是當(dāng)A的值發(fā)生變化時(shí),會(huì)重新給A分配空間,A和B的地址變得不再相同。