Skip to content

[Python] 如何計算變數、物件存取了多少記憶體

Last Updated on 2022-11-24 by Clay

隨著專案開發計畫越來越講究執行速度、記憶體存取率,我們顯然很有必要了解自己的程式中,那些變數啊、物件啊究竟使用了多少的記憶體。

在 Python 中,許多人會推薦內建的 sys.getsizeof() 來返回相關變數、物件的記憶體。但是由於 Python 實作的物件參考機制,所以在許多時候,直接使用內建的這個函式是無法正確地分析出我們究竟使用了多少記憶體。

舉例來說,今天我在使用 HuggingFace 的 transformers 套件,其中我實例化了一個 T5 的 tokenizer,但是若直接使用 sys.getsizeof() 來判斷的話,你會發現 tokenizer 連一個整數變數的記憶體存取量都比不上;這顯然是違背我們的直覺的。

而有一個第三方套件 memory-profiler,則可以正確地幫我們解析。至少在我寫下這篇文章的時候,它正確地運作在了我的程式碼中(2022-11-24)。不過,開發者已經表明不再主動進行維護,但很歡迎想要接手維護的人聯絡他們。

以下我就簡單紀錄該如何使用這個套件分析變數或物件所存取的記憶體。


memory-profiler 使用方法

首先,我們可以透過 pip 指令來安裝它。

pip3 install memory-profiler


接著我們直接來看一段範例程式吧!

# coding: utf-8
from memory_profiler import profile
from transformers import AutoTokenizer


@profile
def main() -> None:
    # Init
    a = 1
    b = list(range(1000))
    tokenizer = AutoTokenizer.from_pretrained("t5-small")

    # Delete
    del a
    del b
    del tokenizer


if __name__ == "__main__":
    main()


Output:

Line #    Mem usage    Increment  Occurrences   Line Contents
=============================================================
     6     75.6 MiB     75.6 MiB           1   @profile
     7                                         def main() -> None:
     8                                             # Init
     9     75.6 MiB      0.0 MiB           1       a = 1
    10     75.6 MiB      0.0 MiB           1       b = list(range(1000))
    11    109.3 MiB     33.7 MiB           1       tokenizer = AutoTokenizer.from_pretrained("t5-small")
    12                                         
    13                                             # Delete
    14    109.3 MiB      0.0 MiB           1       del a
    15    109.3 MiB      0.0 MiB           1       del b
    16    106.4 MiB     -2.9 MiB           1       del tokenizer


就像上方的輸出顯示,我們可以很容易地看到變數或是物件究竟讓這份程式增加了多少記憶體。


References


Read More

Tags:

Leave a Reply