沒(méi)有什么內(nèi)存問(wèn)題,是一行Python代碼解決不了的-創(chuàng)新互聯(lián)

內(nèi)存不足是項(xiàng)目開(kāi)發(fā)過(guò)程中經(jīng)常碰到的問(wèn)題,我和我的團(tuán)隊(duì)在之前的一個(gè)項(xiàng)目中也遇到了這個(gè)問(wèn)題,我們的項(xiàng)目需要存儲(chǔ)和處理一個(gè)相當(dāng)大的動(dòng)態(tài)列表,測(cè)試人員經(jīng)常向我抱怨內(nèi)存不足。但是最終,我們通過(guò)添加一行簡(jiǎn)單的代碼解決了這個(gè)問(wèn)題。

創(chuàng)新互聯(lián)是一家集網(wǎng)站建設(shè),臨澧企業(yè)網(wǎng)站建設(shè),臨澧品牌網(wǎng)站建設(shè),網(wǎng)站定制,臨澧網(wǎng)站建設(shè)報(bào)價(jià),網(wǎng)絡(luò)營(yíng)銷(xiāo),網(wǎng)絡(luò)優(yōu)化,臨澧網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強(qiáng)企業(yè)競(jìng)爭(zhēng)力??沙浞譂M(mǎn)足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時(shí)我們時(shí)刻保持專(zhuān)業(yè)、時(shí)尚、前沿,時(shí)刻以成就客戶(hù)成長(zhǎng)自我,堅(jiān)持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實(shí)用型網(wǎng)站。

結(jié)果如圖所示:
沒(méi)有什么內(nèi)存問(wèn)題,是一行Python代碼解決不了的
我將在下面解釋它的工作原理。
舉一個(gè)簡(jiǎn)單的“l(fā)earning”示例 - 創(chuàng)建一個(gè)DataItem類(lèi),在其中定義一些個(gè)人信息屬性,例如姓名,年齡和地址。沒(méi)有什么內(nèi)存問(wèn)題,是一行Python代碼解決不了的
小測(cè)試——這樣一個(gè)對(duì)象會(huì)占用多少內(nèi)存?
首先讓我們嘗試下面這種測(cè)試方案:
d1 = DataItem("Alex", 42, "-")
print ("sys.getsizeof(d1):", sys.getsizeof(d1))
答案是56字節(jié)??雌饋?lái)比較小,結(jié)果令人滿(mǎn)意。
但是,讓我們檢查另一個(gè)數(shù)據(jù)多一些的對(duì)象:
d2 = DataItem("Boris", 24, "In the middle of nowhere")
print ("sys.getsizeof(d2):", sys.getsizeof(d2))
答案仍然是56。這讓我們明白這個(gè)結(jié)果并不完全正確。
我們的直覺(jué)是對(duì)的,這個(gè)問(wèn)題不是那么簡(jiǎn)單。Python是一種非常靈活的語(yǔ)言,具有動(dòng)態(tài)類(lèi)型,它在工作時(shí)存儲(chǔ)了許多額外的數(shù)據(jù)。這些額外的數(shù)據(jù)本身就占了很多內(nèi)存。
例如,sys.getsizeof(“ ”)返回33,沒(méi)錯(cuò),每個(gè)空行就多達(dá)33字節(jié)!并且sys.getsizeof(1)將為此數(shù)字返回24-24個(gè)字節(jié)(我建議C程序員們現(xiàn)在點(diǎn)擊結(jié)束閱讀,以免對(duì)Python的美麗失去信心)。
對(duì)于更復(fù)雜的元素,例如字典,sys.getsizeof(dict())返回272個(gè)字節(jié),這還只是一個(gè)空字典。舉例到此為止,但事實(shí)已經(jīng)很清楚了,何況RAM的制造商也需要出售他們的芯片。
現(xiàn)在,讓我們回到回到我們的DataItem類(lèi)和“小測(cè)試”問(wèn)題。
這個(gè)類(lèi)到底占多少內(nèi)存?
首先,我們將以較低級(jí)別輸出該類(lèi)的全部?jī)?nèi)容:
def dump(obj):
for attr in dir(obj):
print(" obj.%s = %r" % (attr, getattr(obj, attr)))
這個(gè)函數(shù)將顯示隱藏在“隱身衣”下的內(nèi)容,以便所有Python函數(shù)(類(lèi)型,繼承和其他包)都可以運(yùn)行。
結(jié)果令人印象深刻:
沒(méi)有什么內(nèi)存問(wèn)題,是一行Python代碼解決不了的
當(dāng)前位置:技術(shù)分享 > 技術(shù)參考 > 正文
沒(méi)有什么內(nèi)存問(wèn)題,是一行Python代碼解決不了的
2018-12-18 10:24:56 | 編輯:hely | 查看:96 | 評(píng)論:0
內(nèi)存不足是項(xiàng)目開(kāi)發(fā)過(guò)程中經(jīng)常碰到的問(wèn)題,我和我的團(tuán)隊(duì)在之前的一個(gè)項(xiàng)目中也遇到了這個(gè)問(wèn)題,我們的項(xiàng)目需要存儲(chǔ)和處理一個(gè)相當(dāng)大的動(dòng)態(tài)列表,測(cè)試人員經(jīng)常向我抱怨內(nèi)存不足。但是最終,我們通過(guò)添加一行簡(jiǎn)單的代碼解決了這個(gè)問(wèn)題。
內(nèi)存不足是項(xiàng)目開(kāi)發(fā)過(guò)程中經(jīng)常碰到的問(wèn)題,我和我的團(tuán)隊(duì)在之前的一個(gè)項(xiàng)目中也遇到了這個(gè)問(wèn)題,我們的項(xiàng)目需要存儲(chǔ)和處理一個(gè)相當(dāng)大的動(dòng)態(tài)列表,測(cè)試人員經(jīng)常向我抱怨內(nèi)存不足。但是最終,我們通過(guò)添加一行簡(jiǎn)單的代碼解決了這個(gè)問(wèn)題。
結(jié)果如圖所示:

我將在下面解釋它的工作原理。
舉一個(gè)簡(jiǎn)單的“l(fā)earning”示例 - 創(chuàng)建一個(gè)DataItem類(lèi),在其中定義一些個(gè)人信息屬性,例如姓名,年齡和地址。

小測(cè)試——這樣一個(gè)對(duì)象會(huì)占用多少內(nèi)存?
首先讓我們嘗試下面這種測(cè)試方案:
d1 = DataItem("Alex", 42, "-")
print ("sys.getsizeof(d1):", sys.getsizeof(d1))
答案是56字節(jié)??雌饋?lái)比較小,結(jié)果令人滿(mǎn)意。
但是,讓我們檢查另一個(gè)數(shù)據(jù)多一些的對(duì)象:
d2 = DataItem("Boris", 24, "In the middle of nowhere")
print ("sys.getsizeof(d2):", sys.getsizeof(d2))
答案仍然是56。這讓我們明白這個(gè)結(jié)果并不完全正確。
我們的直覺(jué)是對(duì)的,這個(gè)問(wèn)題不是那么簡(jiǎn)單。Python是一種非常靈活的語(yǔ)言,具有動(dòng)態(tài)類(lèi)型,它在工作時(shí)存儲(chǔ)了許多額外的數(shù)據(jù)。這些額外的數(shù)據(jù)本身就占了很多內(nèi)存。
例如,sys.getsizeof(“ ”)返回33,沒(méi)錯(cuò),每個(gè)空行就多達(dá)33字節(jié)!并且sys.getsizeof(1)將為此數(shù)字返回24-24個(gè)字節(jié)(我建議C程序員們現(xiàn)在點(diǎn)擊結(jié)束閱讀,以免對(duì)Python的美麗失去信心)。
對(duì)于更復(fù)雜的元素,例如字典,sys.getsizeof(dict())返回272個(gè)字節(jié),這還只是一個(gè)空字典。舉例到此為止,但事實(shí)已經(jīng)很清楚了,何況RAM的制造商也需要出售他們的芯片。
現(xiàn)在,讓我們回到回到我們的DataItem類(lèi)和“小測(cè)試”問(wèn)題。
這個(gè)類(lèi)到底占多少內(nèi)存?
首先,我們將以較低級(jí)別輸出該類(lèi)的全部?jī)?nèi)容:
def dump(obj):
for attr in dir(obj):
print(" obj.%s = %r" % (attr, getattr(obj, attr)))
這個(gè)函數(shù)將顯示隱藏在“隱身衣”下的內(nèi)容,以便所有Python函數(shù)(類(lèi)型,繼承和其他包)都可以運(yùn)行。
結(jié)果令人印象深刻:
沒(méi)有什么內(nèi)存問(wèn)題,是一行Python代碼解決不了的它總共占用多少內(nèi)存呢?
在GitHub上,有一個(gè)函數(shù)可以計(jì)算實(shí)際大小,通過(guò)遞歸調(diào)用所有對(duì)象的getsizeof實(shí)現(xiàn)。
沒(méi)有什么內(nèi)存問(wèn)題,是一行Python代碼解決不了的
讓我們?cè)囈幌拢?br/>沒(méi)有什么內(nèi)存問(wèn)題,是一行Python代碼解決不了的
我們分別得到460和484字節(jié),這似乎更接近事實(shí)。
使用這個(gè)函數(shù),我們可以進(jìn)行一系列實(shí)驗(yàn)。例如,我想知道如果DataItem放在列表中,數(shù)據(jù)將占用多少空間。
get_size([d1])函數(shù)返回532個(gè)字節(jié),顯然,這些是“原本的”460+一些額外開(kāi)銷(xiāo)。但是get_size([d1,d2])返回863個(gè)字節(jié)—小于460+484。get_size([d1,d2,d1])的結(jié)果更加有趣,它產(chǎn)生了871個(gè)字節(jié),只是稍微多了一點(diǎn),這說(shuō)明Python很聰明,不會(huì)再為同一個(gè)對(duì)象分配內(nèi)存。
現(xiàn)在我們來(lái)看問(wèn)題的第二部分。
是否有可能減少內(nèi)存消耗?
答案是肯定的。Python是一個(gè)解釋器,我們可以隨時(shí)擴(kuò)展我們的類(lèi),例如,添加一個(gè)新字段:
沒(méi)有什么內(nèi)存問(wèn)題,是一行Python代碼解決不了的
這是一個(gè)很棒的特點(diǎn),但是如果我們不需要這個(gè)功能,我們可以強(qiáng)制解釋器使用slots指令來(lái)指定類(lèi)屬性列表:
沒(méi)有什么內(nèi)存問(wèn)題,是一行Python代碼解決不了的
更多信息可以參考文檔中的“dictweakref的部分。使用dict所節(jié)省的空間可能會(huì)很大”。
我們嘗試后發(fā)現(xiàn):get_size(d1)返回的是64字節(jié),對(duì)比460直接,減少約7倍。作為獎(jiǎng)勵(lì),對(duì)象的創(chuàng)建速度提高了約20%(請(qǐng)參閱文章的第一個(gè)屏幕截圖)。
真正使用如此大的內(nèi)存增益不會(huì)導(dǎo)致其他開(kāi)銷(xiāo)成本。只需添加元素即可創(chuàng)建100,000個(gè)數(shù)組,并查看內(nèi)存消耗:
沒(méi)有什么內(nèi)存問(wèn)題,是一行Python代碼解決不了的
在沒(méi)有slots的情況結(jié)果為16.8MB,而使用slots時(shí)為6.9MB。當(dāng)然不是7倍,但考慮到代碼變化很小,它的表現(xiàn)依然出色。

現(xiàn)在討論一下這種方式的缺點(diǎn)。激活slots會(huì)禁止創(chuàng)建其他所有元素,包括dict,這意味著,例如,下面這種將結(jié)構(gòu)轉(zhuǎn)換為json的代碼將不起作用:
def toJSON(self):
return json.dumps(self.dict)
但這也很容易搞定,可以通過(guò)編程方式生成你的dict,遍歷循環(huán)中的所有元素:
沒(méi)有什么內(nèi)存問(wèn)題,是一行Python代碼解決不了的
向類(lèi)中動(dòng)態(tài)添加新變量也是不可能的,但在我們的項(xiàng)目里,這不是必需的。

下面是最后一個(gè)小測(cè)試。來(lái)看看整個(gè)程序需要多少內(nèi)存。在程序末尾添加一個(gè)無(wú)限循環(huán),使其持續(xù)運(yùn)行,并查看Windows任務(wù)管理器中的內(nèi)存消耗。
沒(méi)有slots時(shí)
沒(méi)有什么內(nèi)存問(wèn)題,是一行Python代碼解決不了的
69Mb變成27Mb......好吧,畢竟我們節(jié)省了內(nèi)存。對(duì)于只添加一行代碼的結(jié)果來(lái)說(shuō)已經(jīng)很好了。
注意:tracemalloc調(diào)試庫(kù)使用了大量額外的內(nèi)存。顯然,它為每個(gè)創(chuàng)建的對(duì)象添加了額外的元素。如果你將其關(guān)閉,總內(nèi)存消耗將會(huì)少得多,截圖顯示了2個(gè)選項(xiàng):
沒(méi)有什么內(nèi)存問(wèn)題,是一行Python代碼解決不了的
如何節(jié)省更多的內(nèi)存?
可以使用numpy庫(kù),它允許你以C風(fēng)格創(chuàng)建結(jié)構(gòu),但在這個(gè)的項(xiàng)目中,它需要更深入地改進(jìn)代碼,所以對(duì)我來(lái)說(shuō)第一種方法就足夠了。
奇怪的是,slots的使用從未在Habré上詳細(xì)分析過(guò),我希望這篇文章能夠填補(bǔ)這一空白。
結(jié)論
這篇文章看起來(lái)似乎是反Python的廣告,但它根本不是。Python是非??煽康?為了“刪除”P(pán)ython中的程序,你必須非常努力),這是一種易于閱讀和方便編寫(xiě)的語(yǔ)言。在許多情況下,這些優(yōu)點(diǎn)遠(yuǎn)勝過(guò)缺點(diǎn),但如果你需要性能和效率的大化,你可以使用numpy庫(kù)像C++一樣編寫(xiě)代碼,它可以非??焖儆行У靥幚頂?shù)據(jù)。

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性?xún)r(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專(zhuān)為企業(yè)上云打造定制,能夠滿(mǎn)足用戶(hù)豐富、多元化的應(yīng)用場(chǎng)景需求。

分享名稱(chēng):沒(méi)有什么內(nèi)存問(wèn)題,是一行Python代碼解決不了的-創(chuàng)新互聯(lián)
鏈接分享:http://muchs.cn/article30/dcjcso.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供App設(shè)計(jì)、外貿(mào)建站、網(wǎng)站排名、全網(wǎng)營(yíng)銷(xiāo)推廣網(wǎng)站維護(hù)、定制網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

小程序開(kāi)發(fā)