メモリ使用状況の取得
前回、「現状のPCのメモリ使用状況を取得する関数psutil」で取得したメモリ使用量とメモリ使用率をグラフ化するプログラムを紹介しました。
今回はメモリ使用状況を把握する方法のもう一つとして「各変数で使用しているメモリ量の取得」を試していきます。
なぜ変数が使用しているメモリ量なのか、詳細は分かりませんが、メモリは情報を一時的に蓄えておくところ、そして変数も同様に情報を一時的に蓄えておくところなので、変数で指定した値はメモリに蓄えられるのだと思われます。
また変数の中身は変わるものなので、その変動を知ることが大切なのだと思います。
そしてプログラムの他の部分に関しては、通常変わらないため、その変化を捉える必要がないと考えられます。
それでは始めていきましょう。
変数のメモリ使用量 その1:sys.getsizeof()
特定の変数のメモリ使用量を取得するには「sysライブラリ」の「getsizeof関数」を使用します。
使い方は「sysライブラリ」をインポートし、「sys.getsizeof(‘変数名’)」です。
import sys
A = 0
B = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
C = {'A':100, 'B':200, 'C':300}
print(sys.getsizeof(A))
print(sys.getsizeof(B))
print(sys.getsizeof(C))
実行結果
24
152
232
変数のメモリ使用量 その2:__sizeof__()
先ほどの例では「sysライブラリ」のインポートが必要でしたが、sysライブラリを使わない方法として、「__sizeof__()」という書き方もあるようです。
この場合は「変数名.__sizeof__()」という形で使用します。
A = 0
B = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
C = {'A':100, 'B':200, 'C':300}
print(A.__sizeof__())
print(B.__sizeof__())
print(C.__sizeof__())
実行結果
24
136
216
リストと辞書において、先ほどの「sys.getsizeof()」と少し値が異なっていますが、詳細は不明です。
変数のメモリ使用量 その3:memory_profiler
上記二つの方法では、変数一つずつに対して、「sys.getsizeof()」や「.__sizeof__()」を指定してやる必要があります。
短いプログラムならいいですが、長いプログラムの場合、なかなかそうもしてられません。
その場合は「memory_profilerライブラリ」を使います。
外部ライブラリなので使う前にpipでインストールが必要です。
pip install memory_profiler
使用するには、メモリ使用量を表示したい変数が入っている関数の前に「@profile」を付けて実行します。
from memory_profiler import profile
@profile
def test():
A = 0
B = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
C = {'A':100, 'B':200, 'C':300}
test()
ただしJupyter Notebook上では「ERROR: Could not find file /var/folders/sp/hg7p80kx22s7vct7yb0zl5cm0000gn/T/ipykernel_76541/870051682.py」といったエラーが出て、実行できませんでした(少なくとも私の環境下では)。
その場合は、実行形式の「pyファイル」を作成し、ターミナル上で実行します。
ipynbファイルを保存したときに同時にpyファイルを保存する方法はこちらです。
これをpyファイルとして実行すると、こんな表が出力されます。
Filename: /Path to py file/MemorySize-2.py
Line # Mem usage Increment Occurrences Line Contents
=============================================================
18 37.9 MiB 37.9 MiB 1 @profile
19 def test():
20 37.9 MiB 0.0 MiB 1 A = 0
21 37.9 MiB 0.0 MiB 1 B = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
22 37.9 MiB 0.0 MiB 1 C = {'A':100, 'B':200, 'C':300}
「Mem usage」がメモリ使用量で、Incrementがその行で増加したメモリ使用量です。
この「@profile」は各関数に必要なので注意してください。
例えばこちらのように「test関数」「test2関数」がある場合、「@profile」は両方の関数の前に追加します。
from memory_profiler import profile
@profile
def test():
A = 0
B = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
C = {'A':100, 'B':200, 'C':300}
@profile
def test2():
D = 100
E = [100, 200, 300, 400, 500]
F = {'D':10, 'E':20, 'F':30, 'G':40, 'H':50}
test()
test2()
実行結果
Filename: /Path to py file/MemorySize-3.py
Line # Mem usage Increment Occurrences Line Contents
=============================================================
18 37.9 MiB 37.9 MiB 1 @profile
19 def test():
20 37.9 MiB 0.0 MiB 1 A = 0
21 37.9 MiB 0.0 MiB 1 B = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
22 37.9 MiB 0.0 MiB 1 C = {'A':100, 'B':200, 'C':300}
Filename: /Path to py file/MemorySize-3.py
Line # Mem usage Increment Occurrences Line Contents
=============================================================
24 37.9 MiB 37.9 MiB 1 @profile
25 def test2():
26 37.9 MiB 0.0 MiB 1 D = 100
27 37.9 MiB 0.0 MiB 1 E = [100, 200, 300, 400, 500]
28 37.9 MiB 0.0 MiB 1 F = {'D':10, 'E':20, 'F':30, 'G':40, 'H':50}
関数の直前に「@profile」がない場合は、その関数のメモリ使用量は表示されません。
from memory_profiler import profile
@profile
def test():
A = 0
B = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
C = {'A':100, 'B':200, 'C':300}
def test2():
D = 100
E = [100, 200, 300, 400, 500]
F = {'D':10, 'E':20, 'F':30, 'G':40, 'H':50}
test()
test2()
実行結果
Filename: /Path to py file/MemorySize-4.py
Line # Mem usage Increment Occurrences Line Contents
=============================================================
19 37.9 MiB 37.9 MiB 1 @profile
20 def test():
21 37.9 MiB 0.0 MiB 1 A = 0
22 37.9 MiB 0.0 MiB 1 B = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
23 37.9 MiB 0.0 MiB 1 C = {'A':100, 'B':200, 'C':300}
また関数の前に「@profile」があったとしても、その関数が実行されていない場合は、メモリ使用量は表示されません。
from memory_profiler import profile
@profile
def test():
A = 0
B = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
C = {'A':100, 'B':200, 'C':300}
@profile
def test2():
D = 100
E = [100, 200, 300, 400, 500]
F = {'D':10, 'E':20, 'F':30, 'G':40, 'H':50}
test()
実行結果
Filename: /Path to py file/MemorySize-5.py
Line # Mem usage Increment Occurrences Line Contents
=============================================================
18 37.9 MiB 37.9 MiB 1 @profile
19 def test():
20 37.9 MiB 0.0 MiB 1 A = 0
21 37.9 MiB 0.0 MiB 1 B = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
22 37.9 MiB 0.0 MiB 1 C = {'A':100, 'B':200, 'C':300}
このように「memory_profilerライブラリ」を使うと簡単に変数の一覧とそれぞれの変数のメモリ使用量を表示することができます。
次回は関連している項目として、プログラムの処理時間を取得する方法を見ていきましょう。
ではでは今回はこんな感じで。
コメント