通過 memory_profiler
來測試優化前後的程式。
上一篇memory_profiler工具的說明介紹
memory_profiler
來比較優化前後的記憶體使用情況。Python版本
3.11.3
1. 原始程式碼:未經優化
這個範例創建了多個大型列表來模擬高記憶體消耗,並展示如何使用 ,執行時間非常久請小心服用
memory_profiler
來分析每一行程式碼的記憶體使用情況。
from memory_profiler import profile
@profile
def create_large_list():
a = [i for i in range(10**7)] # 大列表佔用大量記憶體
b = [i * 2 for i in a] # 創建另一個大列表
c = a.copy() # 複製列表
return b, c
if __name__ == '__main__':
create_large_list()
解析:
- 這段程式創建了一個包含 1000 萬個元素的列表
a
,然後用它來創建另一個大列表b
和c
。這些操作會耗費大量記憶體。 - 運行這段程式時,使用
memory_profiler
可以查看每一步操作的記憶體增長情況。
運行命令:
python -m memory_profiler your_script.py
2. 優化後程式碼:減少記憶體使用
在這裡,我們將通過一些方法來優化記憶體使用。比如,使用生成器(generator)來避免同時在記憶體中保留多個大型列表。
from memory_profiler import profile
# 使用生成器來優化記憶體
@profile
def create_large_list_optimized():
a = (i for i in range(10**7)) # 使用生成器而不是列表
b = (i * 2 for i in a) # 生成器來避免創建大列表
return b
if __name__ == '__main__':
create_large_list_optimized()
解析:
- 這段程式使用了生成器表達式
(i for i in range(10**7))
,來取代列表,生成器是惰性評估的,因此不會立即佔用大量記憶體,而是按需生成元素。 - 生成器的「惰性評估」(也叫延遲求值)指的是生成器不會一次性生成所有結果,而是按需生成,也就是當你需要一個值時,它才計算並返回這個值,而不會提前計算或佔用額外的記憶體。
- 這樣的優化大幅度降低了程式的記憶體使用量,特別是在處理大型數據時。
3. 比較優化前後的記憶體使用
使用 memory_profiler
來比較優化前後的記憶體使用情況:
優化前(未使用生成器)的輸出:

優化後(使用生成器)的輸出:

效益分析
- 未優化版本:每次創建或複製列表時,記憶體的增量非常大(每次增加約 431.1MiB)。如果處理更大的數據集,這樣的記憶體的佔用會迅速增長。
- 優化後版本:使用生成器後,記憶體使用幾乎沒有增加,因為生成器不會一次性將數據載入記憶體,而是隨需求逐步生成數據。
負值說明
- 在 優化前(未使用生成器)的輸出:Line #5 和 Line #6 顯示負的記憶體增量(
-2526.2 MiB
和-17960.5 MiB
),這是異常的情況。通常,這樣的負數是由於記憶體計算的誤差或者是Python分配和釋放記憶體機制的結果導致的。
可能的原因:
- Python 記憶體管理:Python 有自己的記憶體分配和釋放機制,尤其是垃圾回收系統。當你創建大數據結構時,Python 可能會隨著垃圾回收系統的運行,釋放不再使用的記憶體,導致計算出現這樣的異常結果。
- 系統記憶體波動:有時候系統的記憶體分配和釋放過程中也會出現一些波動,特別是在運行大規模記憶體操作時,可能會導致
memory_profiler
讀取記憶體的數據不穩定。