日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 人文社科 > 生活经验 >内容正文

生活经验

python减小内存占用_如何将Python内存占用缩小20倍?

發(fā)布時(shí)間:2023/11/28 生活经验 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python减小内存占用_如何将Python内存占用缩小20倍? 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

當(dāng)程序執(zhí)行過(guò)程中RAM中有大量對(duì)象處于活動(dòng)狀態(tài)時(shí),可能會(huì)出現(xiàn)內(nèi)存問(wèn)題,特別是在對(duì)可用內(nèi)存總量有限制的情況下。

下面概述了一些減小對(duì)象大小的方法,這些方法可以顯著減少純Python程序所需的RAM數(shù)量。

注: 這是我原帖子的英文版本(原帖子是用俄文寫(xiě)的)。(https://habr.com/ru/post/455722/ )

為了簡(jiǎn)單起見(jiàn),我們將考慮用Python中的結(jié)構(gòu)來(lái)表示坐標(biāo)為x、y、z的點(diǎn),并通過(guò)名稱來(lái)訪問(wèn)坐標(biāo)值。

Dict

在小程序中,特別是在腳本中,使用內(nèi)置的dict來(lái)表示結(jié)構(gòu)信息是非常簡(jiǎn)單方便的:

如何將Python內(nèi)存占用縮小20倍?-1.jpg (6.06 KB, 下載次數(shù): 0)

2020-11-8 08:06 上傳

隨著Python 3.6中使用一組有序鍵的更緊湊實(shí)現(xiàn)方式的出現(xiàn),dict變得更有吸引力。但是,讓我們看看它在RAM中的內(nèi)存大小:

如何將Python內(nèi)存占用縮小20倍?-2.jpg (4.43 KB, 下載次數(shù): 0)

2020-11-8 08:06 上傳

它需要大量?jī)?nèi)存,特別是當(dāng)你突然需要?jiǎng)?chuàng)建大量實(shí)例時(shí):

如何將Python內(nèi)存占用縮小20倍?-3.jpg (17.2 KB, 下載次數(shù): 0)

2020-11-8 08:06 上傳

類實(shí)例

對(duì)于那些喜歡將所有東西放置在類中的人來(lái)說(shuō),最好將結(jié)構(gòu)定義為一個(gè)可以通過(guò)屬性名訪問(wèn)的類,:

如何將Python內(nèi)存占用縮小20倍?-4.jpg (10.78 KB, 下載次數(shù): 1)

2020-11-8 08:06 上傳

類實(shí)例的結(jié)構(gòu)很有趣:

如何將Python內(nèi)存占用縮小20倍?-5.jpg (18.95 KB, 下載次數(shù): 0)

2020-11-8 08:06 上傳

這里的__weakref__是對(duì)這個(gè)對(duì)象的所謂弱引用列表的一個(gè)引用,__dict__字段是對(duì)類實(shí)例字典的引用,它包含實(shí)例屬性的值(注意64位的引用平臺(tái)會(huì)占用8個(gè)字節(jié))。從Python 3.3開(kāi)始,共享空間用于在字典中存儲(chǔ)類的所有實(shí)例的鍵。這減少了RAM中實(shí)例堆棧的大小:

如何將Python內(nèi)存占用縮小20倍?-6.jpg (6.8 KB, 下載次數(shù): 0)

2020-11-8 08:06 上傳

因此,大量的類實(shí)例占用的內(nèi)存比一個(gè)普通字典(dict)占用的要小:

如何將Python內(nèi)存占用縮小20倍?-7.jpg (16.23 KB, 下載次數(shù): 0)

2020-11-8 08:06 上傳

很容易看出,由于實(shí)例字典的大小,RAM中實(shí)例的大小依舊很大。

帶有__slots__的類實(shí)例

通過(guò)消除 __dict__和__weakref__,可以顯著減小RAM中的類實(shí)例的大小。這通過(guò)一個(gè)帶有__slots__的小“技巧”是可能實(shí)現(xiàn)的:

如何將Python內(nèi)存占用縮小20倍?-8.jpg (12.89 KB, 下載次數(shù): 0)

2020-11-8 08:06 上傳

RAM中的對(duì)象大小明顯變小了:

如何將Python內(nèi)存占用縮小20倍?-9.jpg (18.05 KB, 下載次數(shù): 0)

2020-11-8 08:06 上傳

在類定義中使用__slots__可以顯著減少大量實(shí)例對(duì)內(nèi)存空間的占用:

如何將Python內(nèi)存占用縮小20倍?-10.jpg (16.62 KB, 下載次數(shù): 0)

2020-11-8 08:06 上傳

目前,這是大幅度減少RAM中類實(shí)例的內(nèi)存占用的主要方法。

這是因?yàn)樵趦?nèi)存中,對(duì)象引用會(huì)緊跟標(biāo)題之后被存儲(chǔ)在內(nèi)存中——屬性值,并通過(guò)類字典中的特殊描述符來(lái)訪問(wèn)它們:

如何將Python內(nèi)存占用縮小20倍?-11.jpg (15 KB, 下載次數(shù): 0)

2020-11-8 08:06 上傳

要自動(dòng)化使用 __slots__創(chuàng)建一個(gè)類的過(guò)程,有一個(gè)庫(kù)[namedlist] (https://pypi.org/project/namedlist )可以使用。namedlist.namedlist函數(shù)會(huì)創(chuàng)建一個(gè)帶有__slots__的類:

如何將Python內(nèi)存占用縮小20倍?-12.jpg (4.88 KB, 下載次數(shù): 1)

2020-11-8 08:06 上傳

另一個(gè)包[attrs] (https://pypi.org/project/attrs )允許你使用和不使用__slots__自動(dòng)創(chuàng)建類。

元組

Python還有一個(gè)內(nèi)置的類型tuple(元組),用于表示不可變的數(shù)據(jù)結(jié)構(gòu)。一個(gè)元組是一個(gè)固定的結(jié)構(gòu)或記錄,但沒(méi)有字段名。對(duì)于字段訪問(wèn),使用的是字段索引。元組字段在元組實(shí)例創(chuàng)建時(shí)就一次性與值對(duì)象相關(guān)聯(lián):

如何將Python內(nèi)存占用縮小20倍?-13.jpg (5.77 KB, 下載次數(shù): 0)

2020-11-8 08:06 上傳

元組的實(shí)例是相當(dāng)簡(jiǎn)潔的:

如何將Python內(nèi)存占用縮小20倍?-14.jpg (4.37 KB, 下載次數(shù): 0)

2020-11-8 08:06 上傳

它們?cè)趦?nèi)存中占用的字節(jié)比使用__slots__的類實(shí)例要多8個(gè)字節(jié),因?yàn)閮?nèi)存中的元組跟蹤也包含許多字段:

如何將Python內(nèi)存占用縮小20倍?-15.jpg (20.47 KB, 下載次數(shù): 1)

2020-11-8 08:06 上傳

Namedtuple(命名元組)

由于元組使用的非常廣泛,某天有人可能會(huì)提交一個(gè)通過(guò)名稱訪問(wèn)字段的請(qǐng)求。這個(gè)請(qǐng)求的答案是collections.namedtuple模塊。

namedtuple函數(shù)的目的是自動(dòng)生成這樣的類:

如何將Python內(nèi)存占用縮小20倍?-16.jpg (4.96 KB, 下載次數(shù): 0)

2020-11-8 08:06 上傳

它會(huì)創(chuàng)建一個(gè)元組子類,其中定義了用于按名稱訪問(wèn)字段的描述符。在我們的例子中,它看起來(lái)是這樣的:

如何將Python內(nèi)存占用縮小20倍?-17.jpg (18.53 KB, 下載次數(shù): 0)

2020-11-8 08:06 上傳

這些類的所有實(shí)例都具有與元組相同的內(nèi)存占用量。大量的實(shí)例會(huì)占用更大的內(nèi)存空間:

如何將Python內(nèi)存占用縮小20倍?-18.jpg (15.94 KB, 下載次數(shù): 0)

2020-11-8 08:06 上傳

Recordclass: 沒(méi)有循環(huán)GC的可變namedtuple

由于tuple和相應(yīng)的namedtuple類會(huì)生成不可變對(duì)象,因此,ob.x屬性就不能再與另一個(gè)值對(duì)象相關(guān)聯(lián)了,對(duì)可變namedtuple變體的請(qǐng)求已經(jīng)出現(xiàn)了。由于Python中沒(méi)有與支持賦值的元組相同的內(nèi)置類型,因此,開(kāi)發(fā)者們創(chuàng)建了許多選項(xiàng)。我們將關(guān)注[recordclass] (https://pypi.org/project/recordclass ),它的評(píng)級(jí)為[stackoverflow] (https://stackoverflow.com/questions/29290359/ exists -of-mutable-name - tuplein -python / 29419745 )。此外,與類元組對(duì)象的大小相比,它還可以用來(lái)減小RAM中對(duì)象的大小。

包recordclass引入了recordclass.mutabletuple類型,它幾乎與tuple相同,但它支持賦值。在此基礎(chǔ)上,創(chuàng)建的子類幾乎與namedtuple完全相同,但它支持將新值賦給字段(不需要?jiǎng)?chuàng)建新的實(shí)例)。recordclass函數(shù)與namedtuple函數(shù)一樣,允許你自動(dòng)創(chuàng)建這些類:

如何將Python內(nèi)存占用縮小20倍?-19.jpg (6.88 KB, 下載次數(shù): 0)

2020-11-8 08:06 上傳

只有在沒(méi)有PyGC_Head的情況下,類實(shí)例才具有與tuple相同的結(jié)構(gòu):

如何將Python內(nèi)存占用縮小20倍?-20.jpg (16.68 KB, 下載次數(shù): 2)

2020-11-8 08:06 上傳

默認(rèn)情況下,recordclass函數(shù)會(huì)創(chuàng)建一個(gè)不參與循環(huán)垃圾回收機(jī)制的類。通常,namedtuple和recordclass用于生成表示記錄或簡(jiǎn)單(非遞歸)數(shù)據(jù)結(jié)構(gòu)的類。在Python中正確使用它們就不會(huì)生成循環(huán)引用。出于這個(gè)原因, 在recordclass生成的類實(shí)例后面 ,默認(rèn)情況下,PyGC_Head 部分會(huì)被排除在外, 這對(duì)支持循環(huán)垃圾回收機(jī)制(更準(zhǔn)確地說(shuō):在與創(chuàng)建的類相關(guān)聯(lián)的PyTypeObject結(jié)構(gòu)中,默認(rèn)情況下,flag字段中的Py_TPFLAGS_HAVE_GC是沒(méi)有設(shè)置的)的類來(lái)說(shuō)是必要的。

大量實(shí)例的內(nèi)存占用量比使用了__slots__的類的實(shí)例要小:

如何將Python內(nèi)存占用縮小20倍?-21.jpg (17.23 KB, 下載次數(shù): 1)

2020-11-8 08:06 上傳

Dataobject

recordclass庫(kù)中提出的另一個(gè)解決方案是基于這樣的思想:在內(nèi)存中使用與帶有__slots__的類實(shí)例相同的存儲(chǔ)結(jié)構(gòu),但不參與循環(huán)垃圾回收機(jī)制。這些類是使用recordclass.make_dataclass數(shù)生成的:

如何將Python內(nèi)存占用縮小20倍?-22.jpg (5.37 KB, 下載次數(shù): 0)

2020-11-8 08:06 上傳

默認(rèn)情況下,以這種方式創(chuàng)建的類將創(chuàng)建可變實(shí)例。

另一種方法——使用繼承自recordclass.dataobject的類聲明:

如何將Python內(nèi)存占用縮小20倍?-23.jpg (5.7 KB, 下載次數(shù): 0)

2020-11-8 08:06 上傳

以這種方式創(chuàng)建的類將創(chuàng)建不參與循環(huán)垃圾回收機(jī)制的實(shí)例。內(nèi)存中實(shí)例的結(jié)構(gòu)與使用__slots__的情況相同,但是沒(méi)有PyGC_Head:

如何將Python內(nèi)存占用縮小20倍?-24.jpg (15.58 KB, 下載次數(shù): 0)

2020-11-8 08:06 上傳

如何將Python內(nèi)存占用縮小20倍?-25.jpg (6.32 KB, 下載次數(shù): 0)

2020-11-8 08:06 上傳

為了訪問(wèn)字段,還可以使用特殊的描述符通過(guò)它從對(duì)象開(kāi)始的偏移量來(lái)訪問(wèn),這些偏移量位于類字典中:

如何將Python內(nèi)存占用縮小20倍?-26.jpg (23.75 KB, 下載次數(shù): 0)

2020-11-8 08:06 上傳

大量實(shí)例內(nèi)存占用量的大小在CPython中可能是最小的:

如何將Python內(nèi)存占用縮小20倍?-27.jpg (17.04 KB, 下載次數(shù): 1)

2020-11-8 08:06 上傳

Cython

還有一種基于使用[Cython] (https://cython.org )的方法。它的優(yōu)點(diǎn)是字段可以接受C語(yǔ)言原子類型的值。自動(dòng)創(chuàng)建用于從純Python中來(lái)訪問(wèn)字段的描述符。例如:

如何將Python內(nèi)存占用縮小20倍?-28.jpg (10.66 KB, 下載次數(shù): 0)

2020-11-8 08:06 上傳

在這種情況下,實(shí)例的內(nèi)存占用更小:

如何將Python內(nèi)存占用縮小20倍?-29.jpg (6.37 KB, 下載次數(shù): 0)

2020-11-8 08:06 上傳

內(nèi)存中的實(shí)例跟蹤的結(jié)構(gòu)如下:

如何將Python內(nèi)存占用縮小20倍?-30.jpg (18.13 KB, 下載次數(shù): 0)

2020-11-8 08:06 上傳

大量副本的占用空間要小一些:

如何將Python內(nèi)存占用縮小20倍?-31.jpg (15.98 KB, 下載次數(shù): 0)

2020-11-8 08:06 上傳

但是,請(qǐng)記住,當(dāng)你從Python代碼訪問(wèn)時(shí),每次都會(huì)執(zhí)行從int到Python對(duì)象的轉(zhuǎn)換,反之亦然。

Numpy

對(duì)大量數(shù)據(jù)使用多維數(shù)組或記錄數(shù)組會(huì)增加內(nèi)存占用。但是,為了在純Python中進(jìn)行有效的處理,你應(yīng)該使用那些主要使用了numpy包中的函數(shù)的處理方法。

如何將Python內(nèi)存占用縮小20倍?-32.jpg (7.62 KB, 下載次數(shù): 0)

2020-11-8 08:06 上傳

使用函數(shù)創(chuàng)建一個(gè)由N個(gè)元素組成的數(shù)組,并將其初始化為0:

如何將Python內(nèi)存占用縮小20倍?-33.jpg (4.91 KB, 下載次數(shù): 0)

2020-11-8 08:06 上傳

內(nèi)存中數(shù)組的大小是可能的最小值:

如何將Python內(nèi)存占用縮小20倍?-34.jpg (16.92 KB, 下載次數(shù): 1)

2020-11-8 08:06 上傳

正常訪問(wèn)數(shù)組元素和行需要將Python對(duì)象轉(zhuǎn)換為C中的 int值,反之亦然。提取單個(gè)行會(huì)創(chuàng)建一個(gè)包含單個(gè)元素的數(shù)組。它的追蹤就不再那么簡(jiǎn)單了:

如何將Python內(nèi)存占用縮小20倍?-35.jpg (4.51 KB, 下載次數(shù): 1)

2020-11-8 08:06 上傳

因此,如上所述,在Python代碼中,有必要使用numpy包中的函數(shù)來(lái)處理數(shù)組。

結(jié)論

通過(guò)一個(gè)清晰而簡(jiǎn)單的示例,可以驗(yàn)證由開(kāi)發(fā)人員和用戶組成的Python編程語(yǔ)言(CPython)社區(qū)確實(shí)有可能顯著減少對(duì)象使用的內(nèi)存量。

英文原文:https://habr.com/en/post/458518/

譯者:Nothing

總結(jié)

以上是生活随笔為你收集整理的python减小内存占用_如何将Python内存占用缩小20倍?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。