メモリ管理¶
概要¶
Python におけるメモリ管理には、全ての Python オブジェクトとデータ構造が入ったプライベートヒープ (private heap) が必須です。プライベートヒープの管理は、内部的には Python メモリマネージャ (Python memory manager) が確実に行います。Python メモリマネージャには、共有 (sharing)、セグメント分割 (segmentation)、事前割り当て (preallocation)、キャッシュ化 (caching) といった、様々な動的記憶管理の側面を扱うために、個別のコンポーネントがあります。
最低水準層では、素のメモリ操作関数 (raw memory allocator) がオペレーティングシステムのメモリ管理機構とやりとりして、プライベートヒープ内にPython 関連の全てのデータを記憶するのに十分な空きがあるかどうか確認します。素のメモリ操作関数の上には、いくつかのオブジェクト固有のメモリ操作関数があります。これらは同じヒープを操作し、各オブジェクト型固有の事情に合ったメモリ管理ポリシを実装しています。例えば、整数オブジェクトは文字列やタプル、辞書とは違ったやり方でヒープ内で管理されます。というのも、整数には値を記憶する上で特別な要件があり、速度/容量のトレードオフが存在するからです。このように、Python メモリマネジャは作業のいくつかをオブジェクト固有のメモリ操作関数に委譲しますが、これらの関数がプライベートヒープからはみ出してメモリ管理を行わないようにしています。
重要なのは、たとえユーザがいつもヒープ内のメモリブロックを指すようなオブジェクトポインタを操作しているとしても、Python 用ヒープの管理はインタプリタ自体が行うもので、ユーザがそれを制御する余地はないと理解することです。Python オブジェクトや内部使用されるバッファを入れるためのヒープ空間のメモリ確保は、必要に応じて、Python メモリマネージャがこのドキュメント内で列挙しているPython/C API 関数群を介して行います。
メモリ管理の崩壊を避けるため、拡張モジュールの作者は決して Python オブジェクトを C ライブラリが公開している関数: malloc() 、 calloc() 、 realloc() および free() で操作しようとしてはなりません。こうした関数を使うと、C のメモリ操作関数と Python メモリマネージャとの間で関数呼び出しが交錯します。 C のメモリ操作関数とPython メモリマネージャは異なるアルゴリズムで実装されていて、異なるヒープを操作するため、呼び出しの交錯は致命的な結果を招きます。とはいえ、個別の目的のためなら、 C ライブラリのメモリ操作関数を使って安全にメモリを確保したり解放したりできます。例えば、以下がそのような例です:
PyObject *res;
char *buf = (char *) malloc(BUFSIZ); /* I/O 用 */
if (buf == NULL)
return PyErr_NoMemory();
...buf を使って何らかの I/O 操作を行う...
res = PyBytes_FromString(buf);
free(buf); /* malloc で割り当て済み */
return res;
この例では、I/O バッファに対するメモリ要求は C ライブラリのメモリ操作関数を使っています。Python メモリマネージャーは戻り値として返される bytes オブジェクトを確保する時にだけ必要です。
In most situations, however, it is recommended to allocate memory from the Python heap specifically because the latter is under control of the Python memory manager. For example, this is required when the interpreter is extended with new object types written in C. Another reason for using the Python heap is the desire to inform the Python memory manager about the memory needs of the extension module. Even when the requested memory is used exclusively for internal, highly specific purposes, delegating all memory requests to the Python memory manager causes the interpreter to have a more accurate image of its memory footprint as a whole. Consequently, under certain circumstances, the Python memory manager may or may not trigger appropriate actions, like garbage collection, memory compaction or other preventive procedures. Note that by using the C library allocator as shown in the previous example, the allocated memory for the I/O buffer completely escapes the Python memory manager.
参考
環境変数 PYTHONMALLOC を使用して Python が利用するメモリアロケータを制御することができます。
環境変数 PYTHONMALLOCSTATS を使用して、新たなオブジェクトアリーナが生成される時と、シャットダウン時に pymalloc メモリアロケータ の統計情報を表示できます。
アロケータドメイン¶
All allocating functions belong to one of three different "domains" (see also
PyMemAllocatorDomain). These domains represent different allocation
strategies and are optimized for different purposes. The specific details on
how every domain allocates memory or what internal functions each domain calls
is considered an implementation detail, but for debugging purposes a simplified
table can be found at デフォルトのメモリアロケータ.
The APIs used to allocate and free a block of memory must be from the same domain.
For example, PyMem_Free() must be used to free memory allocated using PyMem_Malloc().
三つの割り当てドメインは次のとおりです。
Raw domain: intended for allocating memory for general-purpose memory buffers where the allocation must go to the system allocator or where the allocator can operate without the GIL. The memory is requested directly from the system. See Raw Memory Interface.
"Mem" domain: intended for allocating memory for Python buffers and general-purpose memory buffers where the allocation must be performed with the GIL held. The memory is taken from the Python private heap. See Memory Interface.
Object ドメイン: Python オブジェクト用のメモリを割り当てるためのものです。 メモリは Python のプライベートヒープから取得します。 オブジェクトアロケータ を参照してください。
注釈
フリースレッド ビルドでは、object ドメインで割り当てるのは Python オブジェクトだけとし、すべての Python オブジェクトをそのドメインで割り当てる必要があります。 以前の Python では推奨事項にすぎませんでしたが、フリースレッドビルドでは必須の要件です。
例えば、Python オブジェクトではないバッファは PyObject_Malloc() ではなく、PyMem_Malloc()、PyMem_RawMalloc()、malloc() で割り当ててください。
メモリ割り当て API を参照してください。
生メモリインターフェース¶
The following function sets are wrappers to the system allocator. These functions are thread-safe, the GIL does not need to be held.
デフォルトの生メモリアロケータ は malloc()、calloc()、realloc()、free() を使います。
0 バイトの要求には malloc(1) または calloc(1, 1) を呼び出します。
Added in version 3.4.
-
void *PyMem_RawMalloc(size_t n)¶
- 次に属します: Stable ABI (バージョン 3.13 より).
n バイトを割り当て、そのメモリを指す void* 型のポインタを返します。要求が失敗した場合
NULLを返します。0バイトを要求すると、
PyMem_RawMalloc(1)が呼ばれたときと同じように、可能ならNULLでないユニークなポインタを返します。確保されたメモリーにはいかなる初期化も行われません。
-
void *PyMem_RawCalloc(size_t nelem, size_t elsize)¶
- 次に属します: Stable ABI (バージョン 3.13 より).
Allocates nelem elements each of size elsize bytes and returns a pointer of type void* to the allocated memory, or
NULLif the request fails. The memory is initialized to zeros.要素数か要素のサイズが0バイトの要求に対しては、可能なら
PyMem_RawCalloc(1, 1)が呼ばれたのと同じように、ユニークなNULLでないポインタを返します。Added in version 3.5.
-
void *PyMem_RawRealloc(void *p, size_t n)¶
- 次に属します: Stable ABI (バージョン 3.13 より).
p が指すメモリブロックを n バイトにリサイズします。古いサイズと新しいサイズの小さい方までの内容は変更されません。
p が
NULLの場合呼び出しはPyMem_RawMalloc(n)と等価です。そうでなく、 n がゼロに等しい場合、メモリブロックはリサイズされますが解放されません。返されたポインタは非NULLです。p が
NULLでない限り、p はそれより前のPyMem_RawMalloc(),PyMem_RawRealloc(),PyMem_RawCalloc()の呼び出しにより返されなければなりません。要求が失敗した場合
PyMem_RawRealloc()はNULLを返し、 p は前のメモリエリアをさす有効なポインタのままです。
-
void PyMem_RawFree(void *p)¶
- 次に属します: Stable ABI (バージョン 3.13 より).
p が指すメモリブロックを解放します。 p は以前呼び出した
PyMem_RawMalloc(),PyMem_RawRealloc(),PyMem_RawCalloc()の返した値でなければなりません。それ以外の場合やPyMem_RawFree(p)を呼び出した後だった場合、未定義の動作になります。p が
NULLの場合何もしません。
メモリインターフェース¶
以下の関数群が利用して Python ヒープに対してメモリを確保したり解放したり出来ます。これらの関数は ANSI C 標準に従ってモデル化されていますが、0 バイトを要求した際の動作についても定義しています:
The default memory allocator uses the pymalloc memory allocator.
警告
The GIL must be held when using these functions.
バージョン 3.6 で変更: デフォルトのアロケータがシステムの malloc() から pymalloc になりました。
-
void *PyMem_Malloc(size_t n)¶
- 次に属します: Stable ABI.
n バイトを割り当て、そのメモリを指す void* 型のポインタを返します。要求が失敗した場合
NULLを返します。0バイトを要求すると、
PyMem_Malloc(1)が呼ばれたときと同じように、可能ならNULLでないユニークなポインタを返します。 確保されたメモリーにはいかなる初期化も行われません。
-
void *PyMem_Calloc(size_t nelem, size_t elsize)¶
- 次に属します: Stable ABI (バージョン 3.7 より).
Allocates nelem elements each of size elsize bytes and returns a pointer of type void* to the allocated memory, or
NULLif the request fails. The memory is initialized to zeros.要素数か要素のサイズが0バイトの要求に対しては、可能なら
PyMem_Calloc(1, 1)が呼ばれたのと同じように、ユニークなNULLでないポインタを返します。Added in version 3.5.
-
void *PyMem_Realloc(void *p, size_t n)¶
- 次に属します: Stable ABI.
p が指すメモリブロックを n バイトにリサイズします。古いサイズと新しいサイズの小さい方までの内容は変更されません。
p が
NULLの場合呼び出しはPyMem_Malloc(n)と等価です。そうでなく、 n がゼロに等しい場合、メモリブロックはリサイズされますが解放されません。返されたポインタは非NULLです。p が
NULLでない限り、p はそれより前のPyMem_Malloc(),PyMem_Realloc()またはPyMem_Calloc()の呼び出しにより返されなければなりません。要求が失敗した場合
PyMem_Realloc()はNULLを返し、 p は前のメモリエリアをさす有効なポインタのままです。
-
void PyMem_Free(void *p)¶
- 次に属します: Stable ABI.
p が指すメモリブロックを解放します。 p は以前呼び出した
PyMem_Malloc()、PyMem_Realloc()、またはPyMem_Calloc()の返した値でなければなりません。それ以外の場合やPyMem_Free(p)を呼び出した後だった場合、未定義の動作になります。p が
NULLの場合何もしません。
以下に挙げる型対象のマクロは利便性のために提供されているものです。TYPE は任意の C の型を表します。
-
PyMem_New(TYPE, n)¶
PyMem_Malloc()と同じですが、(n * sizeof(TYPE))バイトのメモリを割り当て、TYPE*にキャストしたポインタを返します。 メモリはいかなる方法でも初期化されません。
-
PyMem_Resize(p, TYPE, n)¶
PyMem_Realloc()と同じですが、メモリブロックを(n * sizeof(TYPE))バイトにリサイズし、TYPE*にキャストしたポインタを返します。 戻ったときのpは、新しいメモリ領域へのポインタ、または失敗した場合はNULLです。これは C プリプロセッサマクロです。p は常に再代入されます。エラー処理時にメモリを失うのを避けるには p の元の値を保存してください。
-
void PyMem_Del(void *p)¶
PyMem_Free()と同じです。
Deprecated aliases¶
These are soft deprecated aliases to existing functions and macros. They exist solely for backwards compatibility.
Deprecated alias |
Corresponding function or macro |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
バージョン 3.4 で変更: The macros are now aliases of the corresponding functions and macros. Previously, their behavior was the same, but their use did not necessarily preserve binary compatibility across Python versions.
バージョン 2.0 で非推奨.
オブジェクトアロケータ¶
以下の関数群が利用して Python ヒープに対してメモリを確保したり解放したり出来ます。これらの関数は ANSI C 標準に従ってモデル化されていますが、0 バイトを要求した際の動作についても定義しています:
注釈
メモリアロケータのカスタマイズ で説明する方法でこのドメインの割り当て関数を差し替えて処理を挟む場合、返されるメモリを Python オブジェクトへ安全にキャストできる保証はありません。
The default object allocator uses the pymalloc memory allocator.
警告
The GIL must be held when using these functions.
-
void *PyObject_Malloc(size_t n)¶
- 次に属します: Stable ABI.
n バイトを割り当て、そのメモリを指す void* 型のポインタを返します。要求が失敗した場合
NULLを返します。0バイトを要求すると、
PyObject_Malloc(1)が呼ばれたときと同じように、可能ならNULLでないユニークなポインタを返します。 確保されたメモリーにはいかなる初期化も行われません。
-
void *PyObject_Calloc(size_t nelem, size_t elsize)¶
- 次に属します: Stable ABI (バージョン 3.7 より).
Allocates nelem elements each of size elsize bytes and returns a pointer of type void* to the allocated memory, or
NULLif the request fails. The memory is initialized to zeros.要素数か要素のサイズが0バイトの要求に対しては、可能なら
PyObject_Calloc(1, 1)が呼ばれたのと同じように、ユニークなNULLでないポインタを返します。Added in version 3.5.
-
void *PyObject_Realloc(void *p, size_t n)¶
- 次に属します: Stable ABI.
p が指すメモリブロックを n バイトにリサイズします。古いサイズと新しいサイズの小さい方までの内容は変更されません。
p が
NULLの場合呼び出しはPyObject_Malloc(n)と等価です。そうでなく、 n がゼロに等しい場合、メモリブロックはリサイズされますが解放されません。返されたポインタは非NULLです。p が
NULLでない限り、p はそれより前のPyObject_Malloc(),PyObject_Realloc()またはPyObject_Calloc()の呼び出しにより返されなければなりません。要求が失敗した場合
PyObject_Realloc()はNULLを返し、 p は前のメモリエリアをさす有効なポインタのままです。
-
void PyObject_Free(void *p)¶
- 次に属します: Stable ABI.
p が指すメモリブロックを解放します。 p は以前呼び出した
PyObject_Malloc()、PyObject_Realloc()、またはPyObject_Calloc()の返した値でなければなりません。それ以外の場合やPyObject_Free(p)を呼び出した後だった場合、未定義の動作になります。p が
NULLの場合何もしません。
デフォルトのメモリアロケータ¶
デフォルトのメモリアロケータは次のとおりです。
設定 |
名前 |
PyMem_RawMalloc |
PyMem_Malloc |
PyObject_Malloc |
|---|---|---|---|---|
リリースビルド |
|
|
|
|
デバッグビルド |
|
|
|
|
pymalloc 無しのリリースビルド |
|
|
|
|
pymalloc 無しのデバッグビルド |
|
|
|
|
説明:
名前: 環境変数
PYTHONMALLOCに指定する値。malloc: 標準 C ライブラリのシステムアロケータ。 C 関数malloc()、calloc()、realloc()、free()です。pymalloc: pymalloc メモリアロケータ。mimalloc: mimalloc memory allocator. The pymalloc allocator will be used if mimalloc support isn't available."+ debug": Python メモリアロケータのデバッグフック 付き。
「デバッグビルド」: デバッグモードでの Python ビルド。
メモリアロケータをカスタマイズする¶
Added in version 3.4.
-
type PyMemAllocatorEx¶
メモリブロックのアロケータを記述する構造体です。 以下のフィールドを持ちます。
フィールド
意味
void *ctx第一引数として渡されるユーザコンテキスト
void* malloc(void *ctx, size_t size)メモリブロックを割り当てます
void* calloc(void *ctx, size_t nelem, size_t elsize)0で初期化されたメモリブロックを割り当てます
void* realloc(void *ctx, void *ptr, size_t new_size)メモリブロックを割り当てるかリサイズします
void free(void *ctx, void *ptr)メモリブロックを解放する
バージョン 3.5 で変更:
PyMemAllocator構造体をPyMemAllocatorExに改名し、新しいcallocフィールドを追加しました。
-
type PyMemAllocatorDomain¶
アロケータドメインを同定するための列挙型です。ドメインは:
-
PYMEM_DOMAIN_RAW¶
関数:
-
PYMEM_DOMAIN_MEM¶
関数:
-
PYMEM_DOMAIN_OBJ¶
関数:
-
PYMEM_DOMAIN_RAW¶
-
void PyMem_GetAllocator(PyMemAllocatorDomain domain, PyMemAllocatorEx *allocator)¶
指定されたドメインのメモリブロックアロケータを取得します。
-
void PyMem_SetAllocator(PyMemAllocatorDomain domain, PyMemAllocatorEx *allocator)¶
指定されたドメインのメモリブロックアロケータを設定します。
新しいアロケータは、0バイトを要求されたときユニークな
NULLでないポインタを返さなければなりません。For the
PYMEM_DOMAIN_RAWdomain, the allocator must be thread-safe: the GIL is not held when the allocator is called.For the remaining domains, the allocator must also be thread-safe: the allocator may be called in different interpreters that do not share a
GIL.新しいアロケータがフックでない (1つ前のアロケータを呼び出さない) 場合、
PyMem_SetupDebugHooks()関数を呼び出して、新しいアロケータの上にデバッグフックを再度設置しなければなりません。PyPreConfig.allocatorと PyPreConfig による Python の事前初期化 も参照してください。警告
PyMem_SetAllocator()には次の規約があります。It can be called after
Py_PreInitialize()and beforePy_InitializeFromConfig()to install a custom memory allocator. There are no restrictions over the installed allocator other than the ones imposed by the domain (for instance, the Raw Domain allows the allocator to be called without the GIL held). See the section on allocator domains for more information.Python の初期化完了後 (
Py_InitializeFromConfig()の呼び出し後) に呼び出す場合、アロケータは既存のアロケータを 必ず ラップしなければなりません。 現在のアロケータを別の任意のアロケータで置き換えることは サポートされていません。
バージョン 3.12 で変更: すべてのアロケータがスレッドセーフである必要があります。
-
void PyMem_SetupDebugHooks(void)¶
メモリエラーを検出するために Python メモリアロケータのデバッグフック を設定します。
Python メモリアロケータのデバッグフック¶
デバッグモードで Python をビルドした 場合、Python の事前初期化 で PyMem_SetupDebugHooks() を呼び出し、メモリエラーを検出するデバッグフックをメモリアロケータに設定します。
リリースモードでコンパイルした Python でも、環境変数 PYTHONMALLOC でデバッグフックを設定できます (例: PYTHONMALLOC=debug)。
PyMem_SetAllocator() を呼び出した後で、PyMem_SetupDebugHooks() によってデバッグフックを設定できます。
これらのデバッグフックは、動的に割り当てられたメモリブロックを識別しやすい特別なビットパターンで埋めます。
新しく割り当てたメモリはバイト 0xCD (PYMEM_CLEANBYTE)、解放したメモリはバイト 0xDD (PYMEM_DEADBYTE) で埋めます。
メモリブロックの前後には、バイト 0xFD (PYMEM_FORBIDDENBYTE) で埋めた「禁止バイト」を置きます。
これらのバイトの並びは、有効なアドレス、浮動小数点数、ASCII 文字列にはなりにくいものです。
実行時チェック:
API の誤用を検出します。 例えば、
PyMem_Malloc()で割り当てたメモリブロックにPyObject_Free()を呼び出した場合を検出します。バッファの先頭より前への書き込み (バッファアンダーフロー) を検出します。
バッファの末尾より後への書き込み (バッファオーバーフロー) を検出します。
Check that the GIL is held when allocator functions of
PYMEM_DOMAIN_OBJ(ex:PyObject_Malloc()) andPYMEM_DOMAIN_MEM(ex:PyMem_Malloc()) domains are called.
エラーの場合、デバッグフックは tracemalloc を使って、メモリブロックを割り当てた箇所のトレースバックを取得します。
表示されるのは、tracemalloc が Python のメモリ割り当てを追跡しており、そのブロックが追跡対象だった場合だけです。
Let S = sizeof(size_t). 2*S bytes are added at each end of each block
of N bytes requested. The memory layout is like so, where p represents the
address returned by a malloc-like or realloc-like function (p[i:j] means
the slice of bytes from *(p+i) inclusive up to *(p+j) exclusive; note
that the treatment of negative indices differs from a Python slice):
p[-2*S:-S]元の要求バイト数です。 メモリダンプで読みやすいように、ビッグエンディアンの size_t で格納します。
p[-S]API 識別子 (ASCII 文字)。
PYMEM_DOMAIN_RAWは'r'。PYMEM_DOMAIN_MEMは'm'。PYMEM_DOMAIN_OBJは'o'。
p[-S+1:0]PYMEM_FORBIDDENBYTE の繰り返しです。 領域の手前への書き込みや読み取りを検出するために使います。
p[0:N]要求されたメモリ領域は、未初期化メモリへのアクセスを検出するために PYMEM_CLEANBYTE で埋めます。 realloc 系の関数で領域を拡大した場合、追加部分も PYMEM_CLEANBYTE で埋めます。 free 系の関数を呼び出すと、解放済みメモリへのアクセスを検出するために PYMEM_DEADBYTE で上書きします。 realloc 系の関数で領域を縮小した場合も、不要になった元の領域を PYMEM_DEADBYTE で埋めます。
p[N:N+S]PYMEM_FORBIDDENBYTE の繰り返しです。 領域の後ろへの書き込みや読み取りを検出するために使います。
p[N+S:N+2*S]PYMEM_DEBUG_SERIALNOマクロが定義されている場合だけ使います (デフォルトでは未定義)。malloc 系または realloc 系の関数の呼び出しごとに 1 増える通し番号です。 ビッグエンディアンの
size_tで格納します。 後で「不正なメモリ」を検出した場合、この番号を使って次回の実行でブレークポイントを設定すると、そのブロックを渡した瞬間を捉えられます。 obmalloc.c の静的関数 bumpserialno() だけがこの番号を増やし、そのようなブレークポイントを簡単に設定できるようになっています。
realloc 系や free 系の関数は、まず領域の前後の PYMEM_FORBIDDENBYTE が変わっていないことを確認します。 変更されていれば stderr に診断情報を出力し、Py_FatalError() でプログラムを中止します。 もう一つの主な失敗の形は、プログラムが特別なビットパターンを読み取り、アドレスとして使おうとしてメモリエラーになることです。 その時点でデバッガからオブジェクトを調べると、全体が PYMEM_DEADBYTE (解放済みメモリを使用) または PYMEM_CLEANBYTE (未初期化メモリを使用) で埋まっている可能性が高いです。
バージョン 3.6 で変更: The PyMem_SetupDebugHooks() function now also works on Python
compiled in release mode. On error, the debug hooks now use
tracemalloc to get the traceback where a memory block was allocated.
The debug hooks now also check if the GIL is held when functions of
PYMEM_DOMAIN_OBJ and PYMEM_DOMAIN_MEM domains are
called.
バージョン 3.8 で変更: Windows CRT のデバッグ版 malloc() と free() と同じ値を使うため、バイトパターン 0xCB (PYMEM_CLEANBYTE)、0xDB (PYMEM_DEADBYTE)、0xFB (PYMEM_FORBIDDENBYTE) を、それぞれ 0xCD、0xDD、0xFD に変更しました。
pymalloc アロケータ¶
Python has a pymalloc allocator optimized for small objects (smaller or equal
to 512 bytes) with a short lifetime. It uses memory mappings called "arenas"
with a fixed size of either 256 KiB on 32-bit platforms or 1 MiB on 64-bit
platforms. It falls back to PyMem_RawMalloc() and
PyMem_RawRealloc() for allocations larger than 512 bytes.
pymalloc is the default allocator of the
PYMEM_DOMAIN_MEM (ex: PyMem_Malloc()) and
PYMEM_DOMAIN_OBJ (ex: PyObject_Malloc()) domains.
アリーナアロケータは、次の関数を使います:
Windows では
VirtualAlloc()とVirtualFree()。利用可能なら
mmap()とmunmap()。それ以外の場合は
malloc()とfree()。
--without-pymalloc オプションで Python を構成した場合、このアロケータは無効になります。
環境変数 PYTHONMALLOC で実行時に無効にすることもできます (例: PYTHONMALLOC=malloc)。
Typically, it makes sense to disable the pymalloc allocator when building
Python with AddressSanitizer (--with-address-sanitizer) which helps
uncover low level bugs within the C code.
pymalloc アリーナアロケータのカスタマイズ¶
Added in version 3.4.
-
type PyObjectArenaAllocator¶
アリーナアロケータを記述するための構造体です。3つのフィールドを持ちます:
フィールド
意味
void *ctx第一引数として渡されるユーザコンテキスト
void* alloc(void *ctx, size_t size)size バイトのアリーナを割り当てます
void free(void *ctx, void *ptr, size_t size)アリーナを解放します
-
void PyObject_GetArenaAllocator(PyObjectArenaAllocator *allocator)¶
アリーナアロケータを取得します。
-
void PyObject_SetArenaAllocator(PyObjectArenaAllocator *allocator)¶
アリーナアロケータを設定します。
mimalloc アロケータ¶
Added in version 3.13.
Python supports the mimalloc allocator when the underlying platform support is available. mimalloc "is a general purpose allocator with excellent performance characteristics. Initially developed by Daan Leijen for the runtime systems of the Koka and Lean languages."
tracemalloc C API¶
Added in version 3.7.
-
int PyTraceMalloc_Track(unsigned int domain, uintptr_t ptr, size_t size)¶
割り当てられたメモリブロックを
tracemallocモジュールで追跡します。成功した場合は
0を返し、エラーの場合 (トレースを格納するメモリを割り当てられなかった場合) は-1を返します。 tracemalloc が無効なら-2を返します。そのメモリブロックがすでに追跡されていれば、既存のトレースを更新します。
-
int PyTraceMalloc_Untrack(unsigned int domain, uintptr_t ptr)¶
割り当てられたメモリブロックを
tracemallocモジュールの追跡対象から外します。 追跡されていなければ何もしません。tracemalloc が無効なら
-2、それ以外の場合は0を返します。
使用例¶
最初に述べた関数セットを使って、 概要 節の例を Python ヒープに I/O バッファをメモリ確保するように書き換えたものを以下に示します:
PyObject *res;
char *buf = (char *) PyMem_Malloc(BUFSIZ); /* I/O 用 */
if (buf == NULL)
return PyErr_NoMemory();
/* ...buf を使って何らかの I/O 操作を行う... */
res = PyBytes_FromString(buf);
PyMem_Free(buf); /* PyMem_Malloc で割り当て済み */
return res;
同じコードを型対象の関数セットで書いたものを以下に示します:
PyObject *res;
char *buf = PyMem_New(char, BUFSIZ); /* for I/O */
if (buf == NULL)
return PyErr_NoMemory();
/* ...Do some I/O operation involving buf... */
res = PyBytes_FromString(buf);
PyMem_Del(buf); /* allocated with PyMem_New */
return res;
上の二つの例では、バッファを常に同じ関数セットに属する関数で操作していることに注意してください。実際、あるメモリブロックに対する操作は、異なるメモリ操作機構を混用する危険を減らすために、同じメモリ API ファミリを使って行うことが必要です。以下のコードには二つのエラーがあり、そのうちの一つには異なるヒープを操作する別のメモリ操作関数を混用しているので 致命的 (Fatal) とラベルづけをしています。
char *buf1 = PyMem_New(char, BUFSIZ);
char *buf2 = (char *) malloc(BUFSIZ);
char *buf3 = (char *) PyMem_Malloc(BUFSIZ);
...
PyMem_Del(buf3); /* Wrong -- should be PyMem_Free() */
free(buf2); /* Right -- allocated via malloc() */
free(buf1); /* Fatal -- should be PyMem_Del() */
In addition to the functions aimed at handling raw memory blocks from the Python
heap, objects in Python are allocated and released with PyObject_New,
PyObject_NewVar and PyObject_Del().
これらの関数については、次章の C による新しいオブジェクト型の定義や実装に関する記述の中で説明します。