python内存池机制_python的内存管理机制
一、python是一個(gè)什么樣類型的語言
1、python是一種動(dòng)態(tài)解釋性強(qiáng)類型定義的高級(jí)、通用性編程語言。
解釋型:執(zhí)行的時(shí)候,才一條一條的解釋成機(jī)器語言給計(jì)算機(jī)來執(zhí)行。如:python、js、ruby、PHP等
編譯型:把源程序的每一條語句都編譯成機(jī)器語言,并保存成二進(jìn)制文件,這樣運(yùn)行時(shí)計(jì)算機(jī)可以直接以機(jī)器語言來運(yùn)行此程序,速度快。如:C、C++、go等
動(dòng)態(tài)語言:動(dòng)態(tài)類型的語言編程時(shí),永遠(yuǎn)也不用給任何變量指定數(shù)據(jù)類型,該語言會(huì)在你第一次賦值給變量時(shí),在內(nèi)部將數(shù)據(jù)類型記錄下來
靜態(tài)語言:與動(dòng)態(tài)類型語言剛好相反,它的數(shù)據(jù)類型是在編譯其間檢查的,也就是說在寫程序時(shí)要聲明所有變量的數(shù)據(jù)類型
強(qiáng)類型定義語言:一旦一個(gè)變量被指定了某個(gè)數(shù)據(jù)類型,如果不經(jīng)過強(qiáng)制轉(zhuǎn)換,那么它就永遠(yuǎn)是這個(gè)數(shù)據(jù)類型
弱類型定義語言:數(shù)據(jù)類型可以被忽略的語言。它與強(qiáng)類型定義語言相反, 一個(gè)變量可以賦不同數(shù)據(jù)類型的值
二、python的內(nèi)存管理機(jī)制
python的內(nèi)存管理機(jī)制:引用計(jì)數(shù)、垃圾回收、內(nèi)存池機(jī)制
1、變量與對象
1、變量:通過變量指針引用對象
變量指針:指向具體對象的內(nèi)存空間,取對象的值。
2、對象,類型已知,每個(gè)對象都包含一個(gè)頭部信息(頭部信息:類型標(biāo)識(shí)符和引用計(jì)數(shù)器)
注意:變量名沒有類型,類型屬于對象(因?yàn)樽兞恳脤ο?#xff0c;所以類型隨對象),變量引用什么類型的對象,變量就是什么類型的。
a、容器對象
Python的一個(gè)容器對象(比如:表、詞典等),可以包含多個(gè)對象。
容器對象:容器對象中包含的并不是元素對象本身,是指向各個(gè)元素對象的引用。
1、Python3.6緩存了整數(shù)(-5~256)和短字符串,因此每個(gè)對象在內(nèi)存中只存有一份,引用所指對象就是相同的,即使使用賦值語句,也只是創(chuàng)造新的引用,而不是對象本身;
2、Python沒有緩存長字符串、列表及其他對象,可以有多個(gè)相同的對象,可以使用賦值語句創(chuàng)建出新的對象。
2、引用計(jì)數(shù)
a、普通引用
注意:當(dāng)使用某個(gè)引用作為參數(shù),傳遞給getrefcount()時(shí),參數(shù)實(shí)際上創(chuàng)建了一個(gè)臨時(shí)的引用。因此,getrefcount()所得到的結(jié)果,會(huì)比期望的多1。
b、容器對象
c、引用計(jì)數(shù)增加
1、對象被創(chuàng)建
2、另外的別人被創(chuàng)建
3、作為容器對象的一個(gè)元素
d、引用計(jì)數(shù)減少
1、對象的別名被顯式的銷毀
2、對象的一個(gè)別名被賦值給其他對象
3、對象從一個(gè)窗口對象中移除,或,窗口對象本身被銷毀
4、一個(gè)本地引用離開了它的作用域,比如上面的foo(x)函數(shù)結(jié)束時(shí),x指向的對象引用減1。
3、垃圾回收
從基本原理上,當(dāng)Python的某個(gè)對象的引用計(jì)數(shù)降為0時(shí),說明沒有任何引用指向該對象,該對象就成為要被
回收的垃圾了。比如某個(gè)新建對象,它被分配給某個(gè)引用,對象的引用計(jì)數(shù)變?yōu)?。如果引用被刪除,對象的引
用計(jì)數(shù)為0,那么該對象就可以被垃圾回收。比如下面的表:
a?=[1,2,3]
dela
del a后,已經(jīng)沒有任何引用指向之前建立的[1, 2, 3]這個(gè)表。用戶不可能通過任何方式接觸或者動(dòng)用這個(gè)對象。
這個(gè)對象如果繼續(xù)待在內(nèi)存里,就成了不健康的脂肪。當(dāng)垃圾回收啟動(dòng)時(shí),Python掃描到這個(gè)引用計(jì)數(shù)為0的對象,
就將它所占據(jù)的內(nèi)存清空。
然而,減肥是個(gè)昂貴而費(fèi)力的事情。垃圾回收時(shí),Python不能進(jìn)行其它的任務(wù)。頻繁的垃圾回收將大大降低Python的
工作效率。如果內(nèi)存中的對象不多,就沒有必要總啟動(dòng)垃圾回收。所以,Python只會(huì)在特定條件下,自動(dòng)啟動(dòng)垃圾回收。
當(dāng)Python運(yùn)行時(shí),會(huì)記錄其中分配對象(object allocation)和取消分配對象(object deallocation)的次數(shù)。當(dāng)兩者的差值高于
某個(gè)閾值時(shí),垃圾回收才會(huì)啟動(dòng)。
我們可以通過gc模塊的get_threshold()方法,查看該閾值:
importgc
print(gc.get_threshold())
返回(700, 10, 10),后面的兩個(gè)10是與分代回收相關(guān)的閾值,后面可以看到。700即是垃圾回收啟動(dòng)的閾值。可以
通過gc中的set_threshold()方法重新設(shè)置。
我們也可以手動(dòng)啟動(dòng)垃圾回收,即使用gc.collect()。
分代回收
Python同時(shí)采用了分代(generation)回收的策略。這一策略的基本假設(shè)是,存活時(shí)間越久的對象,越不可能在
后面的程序中變成垃圾。我們的程序往往會(huì)產(chǎn)生大量的對象,許多對象很快產(chǎn)生和消失,但也有一些對象長期被使用。
出于信任和效率,對于這樣一些“長壽”對象,我們相信它們的用處,所以減少在垃圾回收中掃描它們的頻率。
Python將所有的對象分為0,1,2三代。所有的新建對象都是0代對象。當(dāng)某一代對象經(jīng)歷過垃圾回收,依然存活,那么它就
被歸入下一代對象。垃圾回收啟動(dòng)時(shí),一定會(huì)掃描所有的0代對象。如果0代經(jīng)過一定次數(shù)垃圾回收,那么就啟動(dòng)對0代和1代的
掃描清理。當(dāng)1代也經(jīng)歷了一定次數(shù)的垃圾回收后,那么會(huì)啟動(dòng)對0,1,2,即對所有對象進(jìn)行掃描。
這兩個(gè)次數(shù)即上面get_threshold()返回的(700, 10, 10)返回的兩個(gè)10。也就是說,每10次0代垃圾回收,會(huì)配合1次1代的垃圾
回收;而每10次1代的垃圾回收,才會(huì)有1次的2代垃圾回收。
同樣可以用set_threshold()來調(diào)整,比如對2代對象進(jìn)行更頻繁的掃描。
importgc
gc.set_threshold(700,10,5)
4、內(nèi)存池機(jī)制
Python中有分為大內(nèi)存和小內(nèi)存:(256K為界限分大小內(nèi)存)
1、大內(nèi)存使用malloc進(jìn)行分配
2、小內(nèi)存使用內(nèi)存池進(jìn)行分配
3、Python的內(nèi)存池(金字塔)
第3層:最上層,用戶對Python對象的直接操作
第1層和第2層:內(nèi)存池,有Python的接口函數(shù)PyMem_Malloc實(shí)現(xiàn)-----若請求分配的內(nèi)存在1~256字節(jié)之間就
使用內(nèi)存池管理系統(tǒng)進(jìn)行分配,調(diào)用malloc函數(shù)分配內(nèi)存,但是每次只會(huì)分配一塊大小為256K的大塊內(nèi)存,不會(huì)
調(diào)用free函數(shù)釋放內(nèi)存,將該內(nèi)存塊留在內(nèi)存池中以便下次使用。
第0層:大內(nèi)存-----若請求分配的內(nèi)存大于256K,malloc函數(shù)分配內(nèi)存,free函數(shù)釋放內(nèi)存。
第-1,-2層:操作系統(tǒng)進(jìn)行操作
內(nèi)容來自:
總結(jié)
以上是生活随笔為你收集整理的python内存池机制_python的内存管理机制的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java要频繁调用容器时_Java知识点
- 下一篇: java内存分配模型优点_高并发实战(二