Python - メモリ管理とガベージコレクションメカニズム

Python のメモリ管理とガベージ コレクション メカニズム

この知識は面接でよく聞かれるので、記憶力を高めるためにここで整理しておきます。

Python のメモリ管理メカニズムは主に、目標を絞った方法でコードのパフォーマンスを向上させることを目的としています。

メモリ管理メカニズム

より浅いレベルから見ると、Python には 3 種類のメモリ管理があります:
(1) 参照カウント、
(2) ガベージ コレクション、
(3) メモリ プール。

1. 参照カウント

Python では、各オブジェクトには、そのオブジェクトを指す参照の総数、つまり「参照カウント」があります参照カウントは非常に効率的なメモリ管理方法です。Python オブジェクトが参照されると、その参照カウントは 1 増加します。参照されなくなると、参照カウントは 1 減ります。参照カウントが 0 になると、オブジェクトは削除されました。
言葉で表現するのは少し直感的ではないかもしれませんが、他の Web サイトからの図で説明します: C 言語の場合、変数 A を作成するときに、変数のメモリ空間を申請し、変数の値を変数に代入します。 . 空間内で、ある変数を別の変数 B に代入すると、B に新しいメモリ空間が割り当てられ、変数の値が B のメモリ空間に入れられるため、A と B のポインタが不一致になります。 。図に示すように: ここに画像の説明を挿入します
Python では状況が異なります。その処理方法は JavaScript に似ています。
図に示すように、変数はオブジェクトに付けられたラベルに似ています (参照の定義に似ています)。オブジェクト時間、変数の参照カウントは 1 です。システムはこれらのタグを自動的に維持し、定期的にスキャンします。タグの参照カウントが 0 になると、オブジェクトはリサイクルされます。
ここに画像の説明を挿入します

オブジェクトの参照数を確認する: sys.getrefcount()
(1) 共通参照
getrefcount() を使用して、オブジェクトの参照数を確認できます。ここで注意すべき点の 1 つは、参照がパラメーターとして使用されて getrefcount() に渡される場合、そのパラメーターは実際には一時的な参照を作成するため、getrefcount() によって取得される結果は常に予想より 1 多くなるということです。

import sys

a = [1,2,3]
num1 = sys.getrefcount(a)
print(num1)

(2) コンテナオブジェクト
Python のコンテナオブジェクト (テーブル、辞書など) には複数のオブジェクトを含めることができますが、コンテナオブジェクトに含まれるのはオブジェクトそのものではなく、各要素オブジェクトへの参照です。

(3) 参照数が増加します。
ここに画像の説明を挿入します
(4) 参照数が減少します。

ここに画像の説明を挿入します

2. ガベージコレクション

Python のオブジェクトが増えてメモリを占有する量が増えると、不要なオブジェクトを削除するためにガベージ コレクションが開始されます。

Python のガベージ コレクション メカニズムは、主に参照カウント メカニズムに基づく戦略を採用し、マーククリアと世代別コレクション (世代間コレクション) の 2 つのメカニズムによって補完されます。

ガベージ コレクションのメカニズムは主に 3 つのポイントに分かれています:
1) 参照カウント;
2) マーククリア;
参照カウントはほとんどのガベージ コレクションの問題を解決できますが、2 つのオブジェクトが相互に参照する場合、del ステートメントは参照の数を減らすことができますが、参照カウントは 0 に戻らず、オブジェクトは破棄されないため、メモリ リークの問題が発生します。この状況に対処するために、Python はマークスイープメカニズムを導入しました。
ここに画像の説明を挿入します
ここに画像の説明を挿入します

3) 世代別リサイクル
Python は、すべてのオブジェクトを 0、1、2 の 3 つの世代に分割します。すべての
新しいオブジェクトは世代 0 のオブジェクトです。
特定の世代のオブジェクトがガベージ コレクションを経てまだ生きている場合、それらは次の世代のオブジェクトに分類されます。オブジェクト。
ここに画像の説明を挿入します

3. メモリプールの仕組み

ここに画像の説明を挿入します
Python のメモリ メカニズムはピラミッド型になっており、-1 層と -2 層は主にオペレーティング システムによって操作され、
層 0 は C の malloc、free およびその他のメモリ割り当ておよび解放関数によって操作され、
層 1 と 2 は実装されたメモリ プールです。 Python インターフェース関数 PyMem_Malloc 関数によるオブジェクトが 256K 未満の場合、この層は直接メモリを割り当てます; 3 番目の層は
最上位層であり、Python オブジェクトの直接操作です。

256 バイト未満の Python のすべてのオブジェクトは pymalloc によって実装されたアロケーターを使用しますが、それより大きなオブジェクトはシステムの malloc を使用します。さらに、整数、浮動小数点数、リストなどの Python オブジェクトには独自の独立したプライベート メモリ プールがあり、そのメモリ プールはオブジェクト間で共有されません。これは、多数の整数を割り当てて解放すると、これらの整数のキャッシュに使用されるメモリを浮動小数点数に割り当てることができなくなることを意味します。したがって、
Python は 256K を制限として大規模メモリと小規模メモリに分けられます: 1. 大規模メモリは malloc を使用して割り当てられます;
2. 小規模メモリはメモリ プールを使用して割り当てられます。

おすすめ

転載: blog.csdn.net/h21396577548/article/details/109646249