tracemalloc —トレースメモリ割り当て—Pythonドキュメント

提供:Dev Guides
< PythonPython/docs/3.8/library/tracemalloc
移動先:案内検索

tracemalloc —メモリ割り当てをトレースします

バージョン3.4の新機能。


ソースコード: :source: `Lib / tracemalloc.py`



tracemallocモジュールは、Pythonによって割り当てられたメモリブロックをトレースするためのデバッグツールです。 次の情報を提供します。

  • オブジェクトが割り当てられたトレースバック
  • ファイル名ごとおよび行番号ごとに割り当てられたメモリブロックの統計:割り当てられたメモリブロックの合計サイズ、数、および平均サイズ
  • 2つのスナップショットの差を計算して、メモリリークを検出します

Pythonによって割り当てられたほとんどのメモリブロックをトレースするには、 PYTHONTRACEMALLOC 環境変数を1に設定するか、を使用して、モジュールをできるだけ早く起動する必要があります。 -X tracemallocコマンドラインオプション。 tracemalloc.start()関数を実行時に呼び出して、Pythonメモリ割り当てのトレースを開始できます。

デフォルトでは、割り当てられたメモリブロックのトレースには、最新のフレーム(1フレーム)のみが保存されます。 起動時に25フレームを保存するには: PYTHONTRACEMALLOC 環境変数を25に設定するか、 -X tracemalloc=25コマンドを使用しますラインオプション。

トップ10を表示する

最も多くのメモリを割り当てている10個のファイルを表示します。

import tracemalloc

tracemalloc.start()

# ... run your application ...

snapshot = tracemalloc.take_snapshot()
top_stats = snapshot.statistics('lineno')

print("[ Top 10 ]")
for stat in top_stats[:10]:
    print(stat)

Pythonテストスイートの出力例:

[ Top 10 ]
<frozen importlib._bootstrap>:716: size=4855 KiB, count=39328, average=126 B
<frozen importlib._bootstrap>:284: size=521 KiB, count=3199, average=167 B
/usr/lib/python3.4/collections/__init__.py:368: size=244 KiB, count=2315, average=108 B
/usr/lib/python3.4/unittest/case.py:381: size=185 KiB, count=779, average=243 B
/usr/lib/python3.4/unittest/case.py:402: size=154 KiB, count=378, average=416 B
/usr/lib/python3.4/abc.py:133: size=88.7 KiB, count=347, average=262 B
<frozen importlib._bootstrap>:1446: size=70.4 KiB, count=911, average=79 B
<frozen importlib._bootstrap>:1454: size=52.0 KiB, count=25, average=2131 B
<string>:5: size=49.7 KiB, count=148, average=344 B
/usr/lib/python3.4/sysconfig.py:411: size=48.0 KiB, count=1, average=48.0 KiB

Pythonがモジュールから4855 KiBデータ(バイトコードと定数)をロードし、 collections モジュールが244 KiBを割り当てて namedtuple タイプを構築したことがわかります。

その他のオプションについては、 Snapshot.statistics()を参照してください。


違いを計算する

2つのスナップショットを取り、違いを表示します。

import tracemalloc
tracemalloc.start()
# ... start your application ...

snapshot1 = tracemalloc.take_snapshot()
# ... call the function leaking memory ...
snapshot2 = tracemalloc.take_snapshot()

top_stats = snapshot2.compare_to(snapshot1, 'lineno')

print("[ Top 10 differences ]")
for stat in top_stats[:10]:
    print(stat)

Pythonテストスイートのいくつかのテストを実行する前後の出力の例:

[ Top 10 differences ]
<frozen importlib._bootstrap>:716: size=8173 KiB (+4428 KiB), count=71332 (+39369), average=117 B
/usr/lib/python3.4/linecache.py:127: size=940 KiB (+940 KiB), count=8106 (+8106), average=119 B
/usr/lib/python3.4/unittest/case.py:571: size=298 KiB (+298 KiB), count=589 (+589), average=519 B
<frozen importlib._bootstrap>:284: size=1005 KiB (+166 KiB), count=7423 (+1526), average=139 B
/usr/lib/python3.4/mimetypes.py:217: size=112 KiB (+112 KiB), count=1334 (+1334), average=86 B
/usr/lib/python3.4/http/server.py:848: size=96.0 KiB (+96.0 KiB), count=1 (+1), average=96.0 KiB
/usr/lib/python3.4/inspect.py:1465: size=83.5 KiB (+83.5 KiB), count=109 (+109), average=784 B
/usr/lib/python3.4/unittest/mock.py:491: size=77.7 KiB (+77.7 KiB), count=143 (+143), average=557 B
/usr/lib/python3.4/urllib/parse.py:476: size=71.8 KiB (+71.8 KiB), count=969 (+969), average=76 B
/usr/lib/python3.4/contextlib.py:38: size=67.2 KiB (+67.2 KiB), count=126 (+126), average=546 B

Pythonがモジュールデータ(バイトコードと定数)の8173 KiBをロードし、これが前のスナップショットが作成されたときのテスト前にロードされたものより4428 KiB多いことがわかります。 同様に、 linecache モジュールは、Pythonソースコードの940 KiBをキャッシュして、トレースバックをフォーマットしました。これはすべて、前回のスナップショット以降のものです。

システムに空きメモリがほとんどない場合は、 Snapshot.dump()メソッドを使用してスナップショットをディスクに書き込み、スナップショットをオフラインで分析できます。 次に、 Snapshot.load()メソッドを使用してスナップショットをリロードします。


メモリブロックのトレースバックを取得する

最大のメモリブロックのトレースバックを表示するコード:

import tracemalloc

# Store 25 frames
tracemalloc.start(25)

# ... run your application ...

snapshot = tracemalloc.take_snapshot()
top_stats = snapshot.statistics('traceback')

# pick the biggest memory block
stat = top_stats[0]
print("%s memory blocks: %.1f KiB" % (stat.count, stat.size / 1024))
for line in stat.traceback.format():
    print(line)

Pythonテストスイートの出力例(トレースバックは25フレームに制限されています):

903 memory blocks: 870.1 KiB
  File "<frozen importlib._bootstrap>", line 716
  File "<frozen importlib._bootstrap>", line 1036
  File "<frozen importlib._bootstrap>", line 934
  File "<frozen importlib._bootstrap>", line 1068
  File "<frozen importlib._bootstrap>", line 619
  File "<frozen importlib._bootstrap>", line 1581
  File "<frozen importlib._bootstrap>", line 1614
  File "/usr/lib/python3.4/doctest.py", line 101
    import pdb
  File "<frozen importlib._bootstrap>", line 284
  File "<frozen importlib._bootstrap>", line 938
  File "<frozen importlib._bootstrap>", line 1068
  File "<frozen importlib._bootstrap>", line 619
  File "<frozen importlib._bootstrap>", line 1581
  File "<frozen importlib._bootstrap>", line 1614
  File "/usr/lib/python3.4/test/support/__init__.py", line 1728
    import doctest
  File "/usr/lib/python3.4/test/test_pickletools.py", line 21
    support.run_doctest(pickletools)
  File "/usr/lib/python3.4/test/regrtest.py", line 1276
    test_runner()
  File "/usr/lib/python3.4/test/regrtest.py", line 976
    display_failure=not verbose)
  File "/usr/lib/python3.4/test/regrtest.py", line 761
    match_tests=ns.match_tests)
  File "/usr/lib/python3.4/test/regrtest.py", line 1563
    main()
  File "/usr/lib/python3.4/test/__main__.py", line 3
    regrtest.main_in_temp_cwd()
  File "/usr/lib/python3.4/runpy.py", line 73
    exec(code, run_globals)
  File "/usr/lib/python3.4/runpy.py", line 160
    "__main__", fname, loader, pkg_name)

importlib モジュールでは、モジュールからデータ(バイトコードと定数)をロードするために、ほとんどのメモリが割り当てられていることがわかります:870.1 KiB。 トレースバックは、 importlib が最近データをロードした場所です。 doctest モジュールのimport pdb行にあります。 新しいモジュールがロードされると、トレースバックが変更される場合があります。


かなりトップ

<frozen importlib._bootstrap>および<unknown>ファイルを無視して、最も多くのメモリを割り当てている10行をきれいな出力で表示するコード:

import linecache
import os
import tracemalloc

def display_top(snapshot, key_type='lineno', limit=10):
    snapshot = snapshot.filter_traces((
        tracemalloc.Filter(False, "<frozen importlib._bootstrap>"),
        tracemalloc.Filter(False, "<unknown>"),
    ))
    top_stats = snapshot.statistics(key_type)

    print("Top %s lines" % limit)
    for index, stat in enumerate(top_stats[:limit], 1):
        frame = stat.traceback[0]
        print("#%s: %s:%s: %.1f KiB"
              % (index, frame.filename, frame.lineno, stat.size / 1024))
        line = linecache.getline(frame.filename, frame.lineno).strip()
        if line:
            print('    %s' % line)

    other = top_stats[limit:]
    if other:
        size = sum(stat.size for stat in other)
        print("%s other: %.1f KiB" % (len(other), size / 1024))
    total = sum(stat.size for stat in top_stats)
    print("Total allocated size: %.1f KiB" % (total / 1024))

tracemalloc.start()

# ... run your application ...

snapshot = tracemalloc.take_snapshot()
display_top(snapshot)

Pythonテストスイートの出力例:

Top 10 lines
#1: Lib/base64.py:414: 419.8 KiB
    _b85chars2 = [(a + b) for a in _b85chars for b in _b85chars]
#2: Lib/base64.py:306: 419.8 KiB
    _a85chars2 = [(a + b) for a in _a85chars for b in _a85chars]
#3: collections/__init__.py:368: 293.6 KiB
    exec(class_definition, namespace)
#4: Lib/abc.py:133: 115.2 KiB
    cls = super().__new__(mcls, name, bases, namespace)
#5: unittest/case.py:574: 103.1 KiB
    testMethod()
#6: Lib/linecache.py:127: 95.4 KiB
    lines = fp.readlines()
#7: urllib/parse.py:476: 71.8 KiB
    for a in _hexdig for b in _hexdig}
#8: <string>:5: 62.0 KiB
#9: Lib/_weakrefset.py:37: 60.0 KiB
    self.data = set()
#10: Lib/base64.py:142: 59.8 KiB
    _b32tab2 = [a + b for a in _b32tab for b in _b32tab]
6220 other: 3602.8 KiB
Total allocated size: 5303.1 KiB

その他のオプションについては、 Snapshot.statistics()を参照してください。


API

関数

tracemalloc.clear_traces()

Pythonによって割り当てられたメモリブロックのトレースをクリアします。

stop()も参照してください。

tracemalloc.get_object_traceback(obj)

Pythonオブジェクト obj が割り当てられたトレースバックを取得します。 Traceback インスタンスを返します。 tracemalloc モジュールがメモリ割り当てをトレースしていないか、オブジェクトの割り当てをトレースしていない場合は、Noneを返します。

gc.get_referrers()および sys.getsizeof()関数も参照してください。

tracemalloc.get_traceback_limit()

トレースのトレースバックに保存されているフレームの最大数を取得します。

tracemalloc モジュールは、制限を取得するためにメモリ割り当てをトレースしている必要があります。そうでない場合、例外が発生します。

制限は start()関数によって設定されます。

tracemalloc.get_traced_memory()
tracemalloc モジュールによってトレースされたメモリブロックの現在のサイズとピークサイズをタプルとして取得します:(current: int, peak: int)
tracemalloc.get_tracemalloc_memory()
メモリブロックのトレースを格納するために使用される tracemalloc モジュールのメモリ使用量をバイト単位で取得します。 int を返します。
tracemalloc.is_tracing()

True tracemalloc モジュールがPythonメモリ割り当てをトレースしている場合は、False。それ以外の場合。

start()および stop()関数も参照してください。

tracemalloc.start(nframe: int = 1)

Pythonメモリ割り当てのトレースを開始します。Pythonメモリアロケータにフックをインストールします。 収集されるトレースのトレースバックは、 nframe フレームに制限されます。 デフォルトでは、メモリブロックのトレースは最新のフレームのみを保存します。制限は1です。 nframe1以上である必要があります。

1フレームを超えて保存すると、'traceback'でグループ化された統計を計算する場合、または累積統計を計算する場合にのみ役立ちます。 Snapshot.compare_to()および Snapshot.statisticsを参照してください。 ()メソッド。

より多くのフレームを格納すると、 tracemalloc モジュールのメモリとCPUのオーバーヘッドが増加します。 get_tracemalloc_memory()関数を使用して、 tracemalloc モジュールによって使用されているメモリの量を測定します。

PYTHONTRACEMALLOC 環境変数(PYTHONTRACEMALLOC=NFRAME)および -X tracemalloc=NFRAMEコマンドラインオプションを使用して、次の場所でトレースを開始できます。起動。

stop()is_tracing()および get_traceback_limit()関数も参照してください。

tracemalloc.stop()

Pythonメモリ割り当てのトレースを停止します。Pythonメモリアロケータのフックをアンインストールします。 また、Pythonによって割り当てられたメモリブロックの以前に収集されたすべてのトレースをクリアします。

take_snapshot()関数を呼び出して、トレースをクリアする前にトレースのスナップショットを取得します。

start()is_tracing()および clear_traces()関数も参照してください。

tracemalloc.take_snapshot()

Pythonによって割り当てられたメモリブロックのトレースのスナップショットを取ります。 新しい Snapshot インスタンスを返します。

スナップショットには、 tracemalloc モジュールがメモリ割り当てのトレースを開始する前に割り当てられたメモリブロックは含まれていません。

トレースのトレースバックは、 get_traceback_limit()フレームに制限されています。 start()関数の nframe パラメーターを使用して、より多くのフレームを保存します。

tracemalloc モジュールは、スナップショットを取得するためにメモリ割り当てをトレースしている必要があります。 start()関数を参照してください。

get_object_traceback()関数も参照してください。


DomainFilter

class tracemalloc.DomainFilter(inclusive: bool, domain: int)

メモリブロックのトレースをアドレス空間(ドメイン)でフィルタリングします。

バージョン3.6の新機能。

inclusive

inclusiveTrue(include)の場合、アドレス空間 domain に割り当てられているメモリブロックを一致させます。

包括的False(除外)の場合、アドレス空間ドメインに割り当てられていないメモリブロックを一致させます。

domain

メモリブロックのアドレス空間(int)。 読み取り専用プロパティ。


フィルター

class tracemalloc.Filter(inclusive: bool, filename_pattern: str, lineno: int = None, all_frames: bool = False, domain: int = None)

メモリブロックのトレースでフィルタリングします。

filename_pattern の構文については、 fnmatch.fnmatch()関数を参照してください。 '.pyc'ファイル拡張子は'.py'に置き換えられます。

例:

  • Filter(True, subprocess.__file__)には、サブプロセスモジュールのトレースのみが含まれます

  • Filter(False, tracemalloc.__file__)は、 tracemalloc モジュールのトレースを除外します

  • Filter(False, "<unknown>")は空のトレースバックを除外します

バージョン3.5で変更: '.pyo'ファイル拡張子は'.py'に置き換えられなくなりました。

バージョン3.6で変更: domain 属性が追加されました。

domain

メモリブロックのアドレス空間(intまたはNone)。

tracemallocは、ドメイン0を使用して、Pythonによって行われたメモリ割り当てをトレースします。 C拡張機能は、他のドメインを使用して他のリソースをトレースできます。

inclusive

包括的True(包含)の場合、行番号 linenofilename_pattern と一致する名前のファイルに割り当てられたメモリブロックのみを照合します。

包括的False(除外)の場合、行番号 linenofilename_pattern と一致する名前のファイルに割り当てられたメモリブロックを無視します。

lineno

フィルタの行番号(int)。 linenoNoneの場合、フィルターは任意の行番号に一致します。

filename_pattern

フィルタのファイル名パターン(str)。 読み取り専用プロパティ。

all_frames

all_framesTrueの場合、トレースバックのすべてのフレームがチェックされます。 all_framesFalseの場合、最新のフレームのみがチェックされます。

トレースバック制限が1の場合、この属性は効果がありません。 get_traceback_limit()関数および Snapshot.traceback_limit 属性を参照してください。


フレーム

class tracemalloc.Frame

トレースバックのフレーム。

Traceback クラスは、 Frame インスタンスのシーケンスです。

filename

ファイル名(str)。

lineno

行番号(int)。


スナップショット

class tracemalloc.Snapshot

Pythonによって割り当てられたメモリブロックのトレースのスナップショット。

take_snapshot()関数は、スナップショットインスタンスを作成します。

compare_to(old_snapshot: Snapshot, key_type: str, cumulative: bool = False)

古いスナップショットで差を計算します。 key_type でグループ化された StatisticDiff インスタンスのソートされたリストとして統計を取得します。

key_type および cumulative パラメーターについては、 Snapshot.statistics()メソッドを参照してください。

結果は、 StatisticsDiff.size_diffStatisticsDiff.size の絶対値、 StatisticsDiff.count_diffの絶対値によって最大から最小に並べ替えられます。 ] Statistics.count 、次に StatisticsDiff.traceback

dump(filename)

スナップショットをファイルに書き込みます。

load()を使用してスナップショットをリロードします。

filter_traces(filters)

フィルター処理されたトレースシーケンスを使用して新しいスナップショットインスタンスを作成します。フィルタードメインフィルターおよびフィルターインスタンスのリストです。 filters が空のリストの場合は、トレースのコピーを含む新しい Snapshot インスタンスを返します。

すべての包括的フィルターが一度に適用され、それに一致する包括的フィルターがない場合、トレースは無視されます。 少なくとも1つの排他フィルターが一致する場合、トレースは無視されます。

バージョン3.6で変更: DomainFilter インスタンスが filters でも受け入れられるようになりました。

classmethod load(filename)

ファイルからスナップショットをロードします。

dump()も参照してください。

statistics(key_type: str, cumulative: bool = False)

key_type でグループ化された Statistic インスタンスのソートされたリストとして統計を取得します。

key_type

説明

'filename'

ファイル名

'lineno'

ファイル名と行番号

'traceback'

トレースバック

cumulativeTrueの場合、最新のフレームだけでなく、トレースのトレースバックのすべてのフレームのメモリブロックのサイズとカウントを累積します。 累積モードは、 key_type'filename'および'lineno'と等しい場合にのみ使用できます。

結果は、 Statistics.sizeStatistics.countStatistics.traceback の順に、大きいものから小さいものへと並べ替えられます。

traceback_limit

traces のトレースバックに保存されるフレームの最大数:スナップショットが作成されたときの get_traceback_limit()の結果。

traces

Pythonによって割り当てられたすべてのメモリブロックのトレース: Trace インスタンスのシーケンス。

シーケンスの順序は未定義です。 Snapshot.statistics()メソッドを使用して、統計のソートされたリストを取得します。


統計

class tracemalloc.Statistic

メモリ割り当てに関する統計。

Snapshot.statistics()は、 Statistics インスタンスのリストを返します。

StatisticsDiff クラスも参照してください。

count

メモリブロックの数(int)。

size

メモリブロックの合計サイズ(バイト単位)(int)。

traceback

メモリブロックが割り当てられたトレースバック、 Traceback インスタンス。


StatisticDiff

class tracemalloc.StatisticDiff

古い Snapshot インスタンス間のメモリ割り当ての統計的差異。

Snapshot.compare_to()は、 StatisticsDiff インスタンスのリストを返します。 Statistics クラスも参照してください。

count

新しいスナップショットのメモリブロック数(int):メモリブロックが新しいスナップショットで解放されている場合は0

count_diff

古いスナップショットと新しいスナップショットのメモリブロック数の違い(int):メモリブロックが新しいスナップショットに割り当てられている場合は0

size

新しいスナップショットのメモリブロックの合計サイズ(バイト単位)(int):メモリブロックが新しいスナップショットで解放されている場合は0

size_diff

古いスナップショットと新しいスナップショットのメモリブロックの合計サイズのバイト単位の違い(int):0メモリブロックが新しいスナップショットに割り当てられている場合。

traceback

メモリブロックが割り当てられたトレースバック、 Traceback インスタンス。


痕跡

class tracemalloc.Trace

メモリブロックのトレース。

Snapshot.traces 属性は、 Trace インスタンスのシーケンスです。

バージョン3.6で変更: domain 属性が追加されました。

domain

メモリブロックのアドレス空間(int)。 読み取り専用プロパティ。

tracemallocは、ドメイン0を使用して、Pythonによって行われたメモリ割り当てをトレースします。 C拡張機能は、他のドメインを使用して他のリソースをトレースできます。

size

バイト単位のメモリブロックのサイズ(int)。

traceback

メモリブロックが割り当てられたトレースバック、 Traceback インスタンス。


トレースバック

class tracemalloc.Traceback

最も古いフレームから最新のフレームにソートされた Frame インスタンスのシーケンス。

トレースバックには、少なくとも1フレームが含まれています。 tracemallocモジュールがフレームの取得に失敗した場合、行番号0のファイル名"<unknown>"が使用されます。

スナップショットが作成されると、トレースのトレースバックは get_traceback_limit()フレームに制限されます。 take_snapshot()関数を参照してください。

Trace.traceback 属性は、 Traceback インスタンスのインスタンスです。

バージョン3.7での変更:フレームは、最新から最も古いものではなく、最も古いものから最新のものにソートされるようになりました。

format(limit=None, most_recent_first=False)

トレースバックを改行付きの行のリストとしてフォーマットします。 linecache モジュールを使用して、ソースコードから行を取得します。 limit が設定されている場合、 limit が正であれば、 limit の最新フレームをフォーマットします。 それ以外の場合は、abs(limit)の最も古いフレームをフォーマットします。 most_recent_firstTrueの場合、フォーマットされたフレームの順序が逆になり、最後ではなく最初に最新のフレームが返されます。

traceback.format_tb()関数に似ていますが、 format()に改行が含まれていない点が異なります。

例:

print("Traceback (most recent call first):")
for line in traceback:
    print(line)

出力:

Traceback (most recent call first):
  File "test.py", line 9
    obj = Object()
  File "test.py", line 12
    tb = tracemalloc.get_object_traceback(f())