8-5K Star- 檢查 Python 代碼內存分配的利器

【導語】:Memray 是一個可以檢查 Python 代碼內存分配情況的工具,我們可以使用它對 Python 解釋器或擴展模塊中的代碼進行分析,並生成多種統計報告,從而更直觀的看到代碼的內存分配。

簡介

開發者可以根據需要,生成多種統計報告,觀察程序的內存分配。

  1. 總結報告

該報告會把多個線程的內存分配情況顯示到同一個表格中,own memory表示每個函數佔用的內存,total memory表示函數本身及其調用其他函數所佔用的內存總量,allocation count表示暫時未釋放的內存個數。

總結報告

  1. 火焰圖報告 

該報告可以將內存分配數據可視化展示。火焰圖的第一層是佔用內存的函數, 寬度越大,則佔用的內存越多;每一層的函數都被其下一層的函數所調用,依次類推。

def a(n):
    return b(n)

def b(n):
    return [c(n), d(n)]

def c(n):
    return "a" * n

def d(n):
    return "a" * n

a(100000)

火焰圖報告

由該圖可以看出,函數 a 調用了函數 b,函數 b 調用了函數 c 和函數 d。且第一層函數 c 和函數 d 所佔的寬度相同,表示 c 和 d 佔用的內存一樣。

  1. 表格報告

該報告以表格的形式展示程序的內存使用情況。Thread ID表示對應的線程,Size表示佔用的內存總數,Allocator表示佔用內存的函數,Location表示函數所在的位置。同時,還可以對每一列的數據進行排序。

表格報告

  1. 樹形報告

該報告可以清晰的顯示出程序的調用層次。樹形報告中根節點中的內存總量和所佔百分比 只是針對於圖中展示的數據,佔用內存小的不在圖中。

樹形報告

  1. 統計報告

該報告可以顯示程序內存使用情況的詳細信息,包括分配的內存總量、分配類型 (例如MALLOC, CALLOC) 等。

統計報告

項目地址

https://github.com/bloomberg/memray

安裝

目前只能在 Linux 平臺上使用 Memray。由於 Memray 使用了 C 語言,發佈的版本 是二進制的,所以得先在系統上安裝二進制編譯工具。隨後在 Python3.7 + 的環境 下安裝 Memray:

python3 -m pip install memray

如果你想安裝開發版本的 Memray,首先要在系統上安裝二進制工具:libunwind 和liblz4,隨後克隆項目並運行如下命令進行安裝:

git clone git@github.com:bloomberg/memray.git memray
cd memray
python3 -m venv ../memray-env/  # just an example, put this wherever you want
source ../memray-env/bin/activate
python3 -m pip install --upgrade pip
python3 -m pip install -e . -r requirements-test.txt -r requirements-extra.txt

使用

  1. 基本使用

我們可以通過以下命令來追蹤 python 代碼的內存分配情況, my_script.py 就是要分析的文件:

python3 -m memray run my_script.py

也可以把 memray 當作命令行工具使用,例如:

memray run my_script.py
memray run -m my_module

以上命令會輸出一個二進制文件,隨後我們可以根據需要生成統計報告。假如我們想生成一個總結報告,那麼可以運行如下命令:

memray summary my_script.bin

會生成程序內存分配的總結報告:

總結報告

不同的報告形式在簡介部分都有展示,請讀者自行查看。

  1. 分析 C/C++ 代碼的內存分配

當要使用 Memray 分析 numpy 或者 pandas 這種包含 C 代碼的模塊時,我們可以運行如下命令:

memray run --native my_script.py

從而直觀的看到 Python 代碼分配了多少內存,擴展模塊分配了多少內存。

假如我們在一個文件中使用了 Numpy, 當我們不使用--native時,生成的統計報告如下圖:

統計報告

從圖中可以看出在計算 Numpy 數組時分配了內存,但不清楚是 Numpy 還是 Python 解釋器分配了內存。通過使用--native命令,就可以得到一個 更全面的報告,如圖所示:

native 報告

從圖中可以看到 Numpy 中 C 模塊的調用情況,當添加 Numpy 數組後,產生了內存分配。我們可以通過文件的後綴名區分 Python 模塊和 C 模塊。

  1. 在代碼運行時查看內存分配變化

Memray 還支持動態查看 Python 代碼的內存分配情況,我們只需使用以下命令:

memray run --live my_script.py

在這種模式下,開發者可以調試運行時間較長的代碼。下圖即爲文件運行時的內存分配情況:

Live 模式

  1. 結果排序

統計報告中的結果通常是根據分配的總內存,從大到小依次排列。我們可以改變排序條件:

  1. 查看其他線程

使用live命令默認展示的是主線程的內存分配情況,我們可以通過左右箭頭切換到其他線程。

其他線程

  1. API

除了使用memray run查看 Python 代碼的內存分配,還可以在 Python 程序中使用 memray。

import memray

with memray.Tracker("output_file.bin"):
    print("Allocations will be tracked until the with block ends")

更多細節可以查看相關 API 文檔 [1]。

後記

在我們平時編寫 Python 代碼的過程中,有時候只考慮到了業務功能的實現,而忽視了代碼的合理性與規範性,例如內存分配就是一個很重要的點,合理的內存分配有助於 提升項目的運行速度。Memray 就是一個支持查看 Python 代碼內存分配的工具,它的便捷之處在於:我們可以根據需要,生成多種分析報告,從而直觀的瞭解到自己代碼的內存分配情況,避免發生內存泄露現象。

你寫 Python 代碼時關注過內存使用情況嗎?歡迎到評論中分享~

參考資料:

[1]

API 文檔: https://bloomberg.github.io/memray/api.html

Python 開發精選 分享 Python 技術文章、資源、課程、資訊。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/IQ6r_cH4LX61eAalAAnSKg