色婷婷狠狠18禁久久YY,CHINESE性内射高清国产,国产女人18毛片水真多1,国产AV在线观看

python如何管理內(nèi)存

python如何管理內(nèi)存?

在Python 中的對(duì)象越來(lái)越多,占用的內(nèi)存越來(lái)越大,垃圾回收機(jī)制就是將沒(méi)用的對(duì)象清除,釋放內(nèi)存。Python垃圾回收采用引用計(jì)數(shù)機(jī)制為主,標(biāo)記-清除和分代回收機(jī)制為輔的策略,其中標(biāo)記清除機(jī)制用來(lái)解決技術(shù)引用帶來(lái)的循環(huán)引用而無(wú)法釋放內(nèi)存的問(wèn)題,分代回收機(jī)制是為提升垃圾回收的效率。

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

在Python中,每個(gè)對(duì)象都有指向該對(duì)象的引用總數(shù),即引用計(jì)數(shù)(reference count)。一個(gè)對(duì)象會(huì)記錄著引用自己的對(duì)象的個(gè)數(shù),每增加1個(gè)引用,個(gè)數(shù)加1,每減少1個(gè)引用,個(gè)數(shù)減1。在垃圾回收過(guò)程中,利用引用計(jì)數(shù)器方法,在檢測(cè)到對(duì)象引用個(gè)數(shù)為 0 時(shí),對(duì)普通的對(duì)象進(jìn)行釋放內(nèi)存的機(jī)制。

我們可以使用 sys.getrefcount 方法,來(lái)查看每個(gè)對(duì)象的引用計(jì)數(shù)。需要注意的是,當(dāng)使用某個(gè)引用作為參數(shù),傳遞給 getrefcount方法時(shí),參數(shù)實(shí)際上創(chuàng)建了一個(gè)臨時(shí)的引用。因此,getrefcount 方法所得到的結(jié)果比期望的多1。

由上可見(jiàn),l 中的 [t,27] 兩個(gè)元素,都指向了同一個(gè)對(duì)象,實(shí)際上,容器對(duì)象(如,列表、字典等)中包含的并不是元素對(duì)象本身,是指向各個(gè)元素對(duì)象的引用。同時(shí),l 的引用計(jì)數(shù)隨著 ll 的創(chuàng)建和刪除,引用計(jì)數(shù)也隨著增加1和減少1。

導(dǎo)致引用計(jì)數(shù)增加的場(chǎng)景如下:

對(duì)象被創(chuàng)建:t = 27其它的別名被創(chuàng)建:ll = l作為參數(shù)傳遞給函數(shù):getrefcount(l)作為容器對(duì)象的一個(gè)元素:l = [t, 27]

導(dǎo)致引用計(jì)數(shù)減少的場(chǎng)景如下:

對(duì)象的別名被顯式的銷(xiāo)毀:del ll對(duì)象的一個(gè)別名被賦值給其他對(duì)象:l = 789對(duì)象所在的容器被銷(xiāo)毀或從容器中刪除對(duì)象 如,del ll 或 l.remove(t)。一個(gè)本地引用離開(kāi)了它的作用域,比如上面的 getrefcount(x) 函數(shù)結(jié)束時(shí),x指向的對(duì)象引用減1。引用計(jì)數(shù)中的循環(huán)引用

循環(huán)引用即對(duì)象之間進(jìn)行相互引用,出現(xiàn)循環(huán)引用后,利用上述引用計(jì)數(shù)機(jī)制無(wú)法對(duì)循環(huán)引用中的對(duì)象進(jìn)行釋放空間,從而導(dǎo)致內(nèi)存泄漏,這就是循環(huán)引用問(wèn)題,如下:

對(duì)象 test 中的元素引用 ops,而對(duì)象 ops 中元素同時(shí)來(lái)引用 test ,從而造成僅僅刪除 test和 ops對(duì)象,無(wú)法釋放其內(nèi)存空間,因?yàn)樗麄円廊辉诒灰茫ㄒ脗€(gè)數(shù)不為0)。進(jìn)一步解釋就是循環(huán)引用后,test 和 ops 被引用個(gè)數(shù)為2,刪除 test 和 ops 對(duì)象后,兩者被引用的個(gè)數(shù)變?yōu)?,并不是0,而Python只有在檢查到一個(gè)對(duì)象的被引用個(gè)數(shù)為0時(shí),才會(huì)自動(dòng)釋放其內(nèi)存,所以這里無(wú)法釋放 test 和 ops 的內(nèi)存空間,因此這也是導(dǎo)致內(nèi)存泄漏的原因之一。

垃圾回收當(dāng)Python的對(duì)象的引用計(jì)數(shù)降為 0時(shí),說(shuō)明沒(méi)有任何引用指向該對(duì)象,該對(duì)象就成為要被回收的垃圾。比如新建一個(gè)對(duì)象,被賦值給某個(gè)變量,則該對(duì)象的引用計(jì)數(shù)變?yōu)?。如果變量被刪除,對(duì)象的引用計(jì)數(shù)為0,那么該對(duì)象就會(huì)被垃圾回收。

如上,執(zhí)行 del t 后,已經(jīng)沒(méi)有任何引用指向之前建立的對(duì)象 9527,該對(duì)象引用計(jì)數(shù)變?yōu)?,用戶不可能通過(guò)任何方式使用這個(gè)對(duì)象,當(dāng)垃圾回收啟動(dòng)時(shí),Python掃描到這個(gè)引用計(jì)數(shù)為0的對(duì)象,就將它所占用的內(nèi)存進(jìn)行回收。

標(biāo)記-清除機(jī)制——解決循環(huán)引用問(wèn)題

標(biāo)記-清除機(jī)制顧名思義,首先標(biāo)記對(duì)象(垃圾檢測(cè)),然后清除垃圾(垃圾回收),標(biāo)記清除用來(lái)解決引用計(jì)數(shù)機(jī)制產(chǎn)生的循環(huán)引用,進(jìn)而導(dǎo)致內(nèi)存泄漏的問(wèn)題。循環(huán)引用只有在容器對(duì)象才會(huì)產(chǎn)生,比如字典,元組,列表等。首先為了追蹤對(duì)象,需要每個(gè)容器對(duì)象維護(hù)兩個(gè)額外的指針,用來(lái)將容器對(duì)象組成一個(gè)鏈表,指針?lè)謩e指向前后兩個(gè)容器對(duì)象,這樣可以將對(duì)象的循環(huán)引用摘除,就可以得出兩個(gè)對(duì)象的有效計(jì)數(shù),我們通過(guò)如下示例,進(jìn)一步了解一下。

在 標(biāo)記-清除機(jī)制中,存在root鏈表、unreachable鏈表,這里簡(jiǎn)單介紹一下。

如上,在未執(zhí)行 del 語(yǔ)句時(shí),test、ops的引用計(jì)數(shù)都為 2。但是在 del 執(zhí)行完以后,test、ops 引用次數(shù)互相減 1。test、ops陷入循環(huán)引用中,此時(shí)標(biāo)記清除機(jī)制來(lái)打破這種循環(huán)引用,找到其中一端 test 開(kāi)始拆test、ops的引用環(huán)。即從 test 出發(fā),因?yàn)樗幸粋€(gè)對(duì) ops的引用,則將 ops的引用計(jì)數(shù)減1,然后順著引用達(dá)到 ops,因?yàn)?ops有一個(gè)對(duì) test的引用,同樣將 test的引用減1,如此就完成了循環(huán)引用對(duì)象間環(huán)摘除。

引用環(huán)去掉以后發(fā)現(xiàn),test、ops循環(huán)引用變?yōu)榱?,所以test、ops就被添加到 unreachable鏈表 中直接被回收掉。

分代回收機(jī)制-提升垃圾回收效率

解決循環(huán)引用問(wèn)題,引入的標(biāo)記-清除機(jī)制,處理過(guò)程非常繁瑣,需要處理每一個(gè)容器對(duì)象,因此Python考慮一種改善性能的做法,基于“對(duì)象存在時(shí)間越長(zhǎng),越不可能在后面的程序中變成垃圾”的假設(shè),提出分代回收機(jī)制。出于信任和效率,對(duì)于這樣一些“壽命長(zhǎng)”的對(duì)象,我們相信它們的存在價(jià)值,所以降低在垃圾回收中掃描它們的頻率,分代回收是一種以空間換時(shí)間的操作方式。我們可以通過(guò) gc.get_threshold 方法,查看分代回收機(jī)制的參數(shù)閾值設(shè)置,如下:

Python將所有的對(duì)象分為年輕代(第0代)、中年代(第1代)、老年代(第2代)三代。所有的新建對(duì)象默認(rèn)是 第0代對(duì)象。當(dāng)某一代對(duì)象經(jīng)歷過(guò)垃圾回收,若依然存活,那么它就將被劃分到下一代對(duì)象。垃圾回收啟動(dòng)時(shí),會(huì)掃描所有的 第0代對(duì)象。如果 第0代經(jīng)過(guò)一定次數(shù)垃圾回收,那么就觸發(fā)對(duì)0代和1代的掃描清理。當(dāng)?shù)?代也經(jīng)歷了一定次數(shù)的垃圾回收后,那么會(huì)觸發(fā)對(duì) 第0,1,2代,即對(duì)所有對(duì)象進(jìn)行掃描。

如上,gc.get_threshold 方法返回的 (700, 10, 10),700即是垃圾回收啟動(dòng)的閾值,返回的兩個(gè)10是指,每10次0代垃圾回收,會(huì)執(zhí)行1次1代的垃圾回收;而每10次1代的垃圾回收,會(huì)執(zhí)行1次的2代垃圾回收。

同樣可以用 gc.set_threshold 來(lái)調(diào)整分代回收策略,比如對(duì) 第2代對(duì)象進(jìn)行更頻繁的掃描,如下:

通過(guò)此分代回收機(jī)制,循環(huán)引用中的內(nèi)存回收處理過(guò)程就會(huì)得到很大的性能提升。

更加詳細(xì)的介紹可以閱讀下這篇文章《面試中的高頻問(wèn)題,如何理解Python內(nèi)存管理中的垃圾回收機(jī)制》

https://www.toutiao.com/i6741657155532751373/

css resize,python如何管理內(nèi)存