成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

沒有什么內存問題,是一行Python代碼解決不了的

開發 開發工具 后端
內存不足是項目開發過程中經常碰到的問題,我和我的團隊在之前的一個項目中也遇到了這個問題,我們的項目需要存儲和處理一個相當大的動態列表,測試人員經常向我抱怨內存不足。但是最終,我們通過添加一行簡單的代碼解決了這個問題。

Python代碼

大數據文摘出品

編譯:Javen、胡笳、云舟

內存不足是項目開發過程中經常碰到的問題,我和我的團隊在之前的一個項目中也遇到了這個問題,我們的項目需要存儲和處理一個相當大的動態列表,測試人員經常向我抱怨內存不足。但是最終,我們通過添加一行簡單的代碼解決了這個問題。

結果如圖所示:

Python代碼

我將在下面解釋它的工作原理。

舉一個簡單的“learning”示例 - 創建一個DataItem類,在其中定義一些個人信息屬性,例如姓名,年齡和地址。

  1. class DataItem(object): 
  2.    def __init__(self, name, age, address): 
  3.        self.name = name 
  4.        self.age = age 
  5.        self.address = address 

小測試——這樣一個對象會占用多少內存?

首先讓我們嘗試下面這種測試方案:

  1. d1 = DataItem("Alex", 42, "-") 
  2. print ("sys.getsizeof(d1):", sys.getsizeof(d1)) 

答案是56字節。看起來比較小,結果令人滿意。

但是,讓我們檢查另一個數據多一些的對象:

  1. d2 = DataItem("Boris", 24, "In the middle of nowhere") 
  2. print ("sys.getsizeof(d2):", sys.getsizeof(d2)) 

答案仍然是56。這讓我們明白這個結果并不完全正確。

我們的直覺是對的,這個問題不是那么簡單。Python是一種非常靈活的語言,具有動態類型,它在工作時存儲了許多額外的數據。這些額外的數據本身就占了很多內存。

例如,sys.getsizeof(“ ”)返回33,沒錯,每個空行就多達33字節!并且sys.getsizeof(1)將為此數字返回24-24個字節(我建議C程序員們現在點擊結束閱讀,以免對Python的美麗失去信心)。

對于更復雜的元素,例如字典,sys.getsizeof(dict())返回272個字節,這還只是一個空字典。舉例到此為止,但事實已經很清楚了,何況RAM的制造商也需要出售他們的芯片。

現在,讓我們回到回到我們的DataItem類和“小測試”問題。

這個類到底占多少內存?

首先,我們將以較低級別輸出該類的全部內容:

  1. def dump(obj): 
  2.  for attr in dir(obj): 
  3.    print("  obj.%s = %r" % (attr, getattr(obj, attr))) 

這個函數將顯示隱藏在“隱身衣”下的內容,以便所有Python函數(類型,繼承和其他包)都可以運行。

結果令人印象深刻:

它總共占用多少內存呢?

在GitHub上,有一個函數可以計算實際大小,通過遞歸調用所有對象的getsizeof實現。

  1. def get_size(obj, seen=None): 
  2.    # From https://goshippo.com/blog/measure-real-size-any-python-object/ 
  3.    # Recursively finds size of objects 
  4.    size = sys.getsizeof(obj) 
  5.    if seen is None: 
  6.        seen = set() 
  7.    obj_id = id(obj) 
  8.    if obj_id in seen: 
  9.        return 0 
  10.  
  11. # Important mark as seen *before* entering recursion to gracefully handle 
  12.    # self-referential objects 
  13.    seen.add(obj_id) 
  14.    if isinstance(obj, dict): 
  15.      size += sum([get_size(v, seen) for v in obj.values()]) 
  16.      size += sum([get_size(k, seen) for k in obj.keys()]) 
  17.    elif hasattr(obj, '__dict__'): 
  18.      size += get_size(obj.__dict__, seen) 
  19.    elif hasattr(obj, '__iter__') and not isinstance(obj, (str, bytes, bytearray)): 
  20.      size += sum([get_size(i, seen) for i in obj]) 
  21.    return size 

讓我們試一下:

  1. d1 = DataItem("Alex", 42, "-") 
  2. print ("get_size(d1):", get_size(d1)) 
  3.  
  4. d2 = DataItem("Boris", 24, "In the middle of nowhere") 
  5. print ("get_size(d2):", get_size(d2)) 

我們分別得到460和484字節,這似乎更接近事實。

使用這個函數,我們可以進行一系列實驗。例如,我想知道如果DataItem放在列表中,數據將占用多少空間。

get_size([d1])函數返回532個字節,顯然,這些是“原本的”460+一些額外開銷。但是get_size([d1,d2])返回863個字節—小于460+484。get_size([d1,d2,d1])的結果更加有趣,它產生了871個字節,只是稍微多了一點,這說明Python很聰明,不會再為同一個對象分配內存。

現在我們來看問題的第二部分。

是否有可能減少內存消耗?

答案是肯定的。Python是一個解釋器,我們可以隨時擴展我們的類,例如,添加一個新字段:

  1. d1 = DataItem("Alex", 42, "-") 
  2. print ("get_size(d1):", get_size(d1)) 
  3.  
  4. d1.weight = 66 
  5. print ("get_size(d1):", get_size(d1)) 

這是一個很棒的特點,但是如果我們不需要這個功能,我們可以強制解釋器使用__slots__指令來指定類屬性列表:

  1. class DataItem(object): 
  2.    __slots__ = ['name', 'age', 'address'] 
  3.    def __init__(self, name, age, address): 
  4.        self.name = name 
  5.        self.age = age 
  6.        self.address = address 

更多信息可以參考文檔中的“__dict__和__weakref__的部分。使用__dict__所節省的空間可能會很大”。

我們嘗試后發現:get_size(d1)返回的是64字節,對比460直接,減少約7倍。作為獎勵,對象的創建速度提高了約20%(請參閱文章的第一個屏幕截圖)。

真正使用如此大的內存增益不會導致其他開銷成本。只需添加元素即可創建100,000個數組,并查看內存消耗:

  1. data = [] 
  2. for p in range(100000): 
  3.    data.append(DataItem("Alex", 42, "middle of nowhere")) 
  4.  
  5. snapshot = tracemalloc.take_snapshot() 
  6. top_stats = snapshot.statistics('lineno') 
  7. total = sum(stat.size for stat in top_stats) 
  8. print("Total allocated size: %.1f MB" % (total / (1024*1024))) 

在沒有__slots__的情況結果為16.8MB,而使用__slots__時為6.9MB。當然不是7倍,但考慮到代碼變化很小,它的表現依然出色。

現在討論一下這種方式的缺點。激活__slots__會禁止創建其他所有元素,包括__dict__,這意味著,例如,下面這種將結構轉換為json的代碼將不起作用:

  1. def toJSON(self): 
  2.        return json.dumps(self.__dict__) 

但這也很容易搞定,可以通過編程方式生成你的dict,遍歷循環中的所有元素:

  1. def toJSON(self): 
  2.        data = dict() 
  3.        for var in self.__slots__: 
  4.            data[var] = getattr(self, var) 
  5.        return json.dumps(data) 

向類中動態添加新變量也是不可能的,但在我們的項目里,這不是必需的。

下面是最后一個小測試。來看看整個程序需要多少內存。在程序末尾添加一個無限循環,使其持續運行,并查看Windows任務管理器中的內存消耗。

沒有__slots__時

69Mb變成27Mb......好吧,畢竟我們節省了內存。對于只添加一行代碼的結果來說已經很好了。

注意:tracemalloc調試庫使用了大量額外的內存。顯然,它為每個創建的對象添加了額外的元素。如果你將其關閉,總內存消耗將會少得多,截圖顯示了2個選項:

如何節省更多的內存?

可以使用numpy庫,它允許你以C風格創建結構,但在這個的項目中,它需要更深入地改進代碼,所以對我來說第一種方法就足夠了。

奇怪的是,__slots__的使用從未在Habré上詳細分析過,我希望這篇文章能夠填補這一空白。

結論

這篇文章看起來似乎是反Python的廣告,但它根本不是。Python是非常可靠的(為了“刪除”Python中的程序,你必須非常努力),這是一種易于閱讀和方便編寫的語言。在許多情況下,這些優點遠勝過缺點,但如果你需要性能和效率的最大化,你可以使用numpy庫像C++一樣編寫代碼,它可以非常快速有效地處理數據。

最后,祝你編程愉快!

相關報道:

https://medium.com/@alexmaisiura/python-how-to-reduce-memory-consumption-by-half-by-adding-just-one-line-of-code-56be6443d524

【本文是51CTO專欄機構大數據文摘的原創譯文,微信公眾號“大數據文摘( id: BigDataDigest)”】

     大數據文摘二維碼

戳這里,看該作者更多好文

責任編輯:趙寧寧 來源: 51CTO專欄
相關推薦

2020-09-23 09:40:17

內存Python代碼

2022-02-23 14:37:48

代碼Pythonbug

2023-04-05 20:14:32

AIChatGPT

2021-07-22 16:23:23

亞馬遜微軟

2019-07-31 08:30:24

物聯網電池能源

2016-12-02 08:53:18

Python一行代碼

2016-01-06 11:40:24

2020-07-27 10:37:01

編程技巧開發

2025-03-05 11:00:00

JavaScript跨域前端

2025-04-17 08:05:00

JavaScript

2022-02-24 10:40:14

Python代碼

2021-11-02 16:25:41

Python代碼技巧

2022-04-09 09:11:33

Python

2020-08-12 14:54:00

Python代碼開發

2017-04-05 11:10:23

Javascript代碼前端

2020-10-13 17:30:45

Python代碼內存

2020-08-19 10:30:25

代碼Python多線程

2017-04-13 19:20:18

Python代碼并行任務

2021-09-22 09:43:47

Python 開發編程語言

2021-05-28 07:39:17

SQL代碼操作
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 精品不卡| 天天宗合网 | 秋霞影院一区二区 | 国产精品一区二区在线 | 精品毛片 | 午夜无码国产理论在线 | 久久国产精品99久久久久 | 久久久久久国产精品免费免费男同 | 国产成人免费视频 | 亚洲小视频在线观看 | 亚洲精品一区二区三区蜜桃久 | 特黄色毛片 | 日韩欧美三级电影在线观看 | 在线一区视频 | 国产日产精品一区二区三区四区 | 国产一区二区三区 | 在线观看视频一区 | 国产在线不卡 | 国产精品一区在线观看 | 日韩欧美精品 | 久久蜜桃精品 | 亚洲精品女优 | 五月天天丁香婷婷在线中 | 日韩精品一区在线观看 | 欧美1区2区 | 国产精品伦理一区二区三区 | 国产在线视频网 | 男女免费观看在线爽爽爽视频 | 日韩欧美三区 | 久久精品国产亚洲 | av福利网| 国产高清在线精品一区二区三区 | 日批的视频 | 国产亚洲欧美在线视频 | 自拍偷拍精品 | 欧美高清免费 | 久久免费观看一级毛片 | 国产精品日日夜夜 | 九九导航| 国产成视频在线观看 | 艹逼网|