解決するにはPythonのメモリ管理およびガベージコレクションのアルゴリズム

この記事では、解像度のアルゴリズムPythonのメモリ管理およびガベージコレクションを紹介し、伝統的なガベージコレクションのメカニズム、仕事のそのメソッド、ファイナライザの問題やその他の関連コンテンツを導入し、一定の基準値を持っている、必要性の友人は、次を理解することができます。
概要

リスト、タプル、インスタンス、クラス、辞書や関数循環参照の問題が存在します。そこデル方法の例は、サウンド的に処理されます。GCのサポートの新しいタイプを追加するには非常に簡単です。GCとは、通常のPython Pythonはバイナリ互換でサポートされています。

世代回復の実行作業(現在は3世代)。pybenchで測定した結果は、4%のオーバーヘッドについてです。事実上すべての拡張モジュールが(私は新しいとはcPickleモジュールの標準のリリースを変更する必要がありました)適切同じ作業のままであるべきです。GCすぐにデバッガと呼ばれる新しいモジュールには、オプションを回復し、セットデバッグするために使用することができます

コレクターは、プラットフォーム間で移植する必要があります。パッチのPythonのバージョンは何の問題もなく杯、アイドルと時間のスケッチを実行するために、すべてのテストとリターンを過ぎています。

Pythonの2.0およびそれ以降のバージョンので、携帯ガベージコレクションは、その中に含まれています。ガベージコレクションは、デフォルトで有効になっています。それのいくつか嬉しいてください!

なぜ我々は、ガベージコレクションが必要なのでしょうか?

Pythonの現在のバージョンは、メモリ割り当てを管理するための参照カウントを使用します。各オブジェクトは、この参照カウントは、それを指すオブジェクトの数を示し、参照カウントのPythonを持っています。参照カウントが0の場合、オブジェクトが解放されます。ほとんどのプログラムのための参照カウントがうまく動作します。しかし、欠陥のある自然の参照カウントは、循環参照のために発生します。循環参照の最も単純な例では、オブジェクト自体への参照です。例えば:

>>> l = []
>>> l.append(l)
>>> del l

これは、参照カウントのリストは、現在1で作成しました。しかし、それは、Python内から既にアクセスできないので、再度使用することができない、それはゴミとして扱われるべきです。Pythonの現在のバージョンでは、このリストは解放されることはありません。

循環参照は、一般的には良いプログラミングの練習ではなく、ほとんど常に避けています。しかし、時には循環参照を作成しないようにすることは困難である、またはプログラマでも、循環参照の問題を認識していません。プログラムを長時間実行するために、サーバなど、この問題は特に気になります。人々は彼らのサーバーがあるため、メモリが使い果たされてアクセスすることができない循環参照オブジェクトを解放することはできませんしたくありません。大規模なプログラムでは、どのようにハード循環参照が作成されて見つけることができます。

「伝統的な」ガベージコレクションは何ですか?

伝統的な(例えばマークとして - スイープ法または停止 - コピー方法)ガベージコレクション次のように一般的です。

ルートオブジェクトシステムを検索します。ルートオブジェクトは、グローバル(例えばにおけるPythonなどの環境に似ているメインモジュール)とオブジェクトスタック上。
これらのオブジェクトからアクセスできるすべてのオブジェクトを検索します。これらのオブジェクトは「アクティブ」です。
他のすべてのオブジェクトの解放。
残念ながら、この方法は、Pythonの現行バージョンには使用できません。膨張仕事モジュールので、Pythonは完全にオブジェクトのルート・セットを決定しません。オブジェクトのルートセットを正確に決定することができない場合、我々はまだ参照されたオブジェクトの解放の危険性を持っています。他の拡張モジュールの使用は、現在のCのスタック上のポータブル・オブジェクトを検索する方法はありませんように設計 また、参照カウントは、すでに利益と終了のセマンティクスに関するメモリ参照の局所性を楽しみにしていくつかのPythonプログラマを提供します。我々が使用することができます参照カウントを見つけることができます、だけでなく、循環参照のスキームを解除することができる最高。

どのようにこの方法で動作しますか?

概念的には、この方法で、伝統的なガベージコレクション機構反対。すべてのアクセス不能なオブジェクトを見つけるのではなく、すべてのアクセス可能なオブジェクトを移動するには、この方法を試み。この方法は、少なくともではない(私たちの時間と空間を無駄に関係なく)よりも悪いガベージコレクションせずに、失敗した場合ので、それは、はるかに安全です。

我々は、参照カウントのガベージコレクタとに残っているので唯一の循環参照を見つける必要があります。参照カウントは、廃棄物の他のタイプを扱います。まず、循環参照が唯一のコンテナオブジェクトを作成することができることを観察しました。コンテナオブジェクトは、参照することができる他のオブジェクトを含むオブジェクトです。Pythonでは、リスト、辞書、インスタンス、クラス及び例は、祖先コンテナオブジェクトです。整数と文字列はコンテナではありません。この発見により、我々は、非コンテナ・オブジェクトがガベージ無視リサイクルできることに気づきました。これは、整数や文字列は、比較的軽いべきであるとして有用な最適化です。

今、アイデアは、すべてのコンテナオブジェクトを記録することです。行うには、いくつかの方法がありますが、しかし、最善の方法は、二重リンクリストを使用することで、オブジェクト構造内のリンクされたリストは、ポインタフィールドを含みます。素早くコレクションから削除されたオブジェクトを挿入することができ、および追加のメモリ割り当てを必要としない、あなたはそう。コンテナが作成されると、それは、このコレクションに挿入され、削除され、それがコレクションから削除されます。

今、私たちは、すべてのコンテナオブジェクトを得ることができることを、どのように我々は、循環参照を見つけるのですか?まず、二つのポインタの外側コンテナオブジェクトに別のフィールドを追加します。我々はこの分野のgc_refsを命名します。私たちは、次の手順で循環参照を見つけることができます。

各コンテナオブジェクト、提供gc_refsオブジェクトの参照カウント値。
他の容器を見つけるために各コンテナオブジェクトは、参照と値そのgc_refsマイナス1、それをオブジェクト。
全てgc_refsコンテナオブジェクトは、容器の外側にオブジェクトのコレクションによって参照される1つのより大きいオブジェクトです。私たちは別のコレクションにこれらのオブジェクトを置くように、我々は、これらのオブジェクトを解放することはできません。
オブジェクトが参照されたオブジェクトを解放することができません削除されます。私たちは、それらを置くと、それらにオブジェクトへのアクセス権を与えるには、現在のコレクションから削除されます。
残りのオブジェクトの現在のコレクションにのみコレクション内のオブジェクトによって参照される(すなわち、それらはゴミであるパイソン、に取り込むことができません)。私たちは今、これらのオブジェクトを解放することができます。
ファイナライザ問題

私たちの壮大な計画は問題があり、問題は、ファイナライザを使用することです。Pythonでの例ファイナライザ__del__の方法です。参照カウントを使用する場合は、ファイナライザはうまく動作します。オブジェクトの参照カウントが0になったときにオブジェクトが呼び出される前に、ファイナライザがリリースされたばかりのとき。プログラマにとって、これは簡単で理解しやすいです。

ガベージコレクションは、呼び出すとファイナライザは、循環参照の問題に直面した場合は特に、厄介な問題となっています。循環参照で2つのオブジェクトがファイナライザがある場合は、どのようにしますか?これは最初の呼び出し?二ファイナライザはそれを得ることができますので、最初のファイナライザを呼び出した後、オブジェクトを解除することができません。

この問題に対する良い解決策が存在しないので、参照されるオブジェクトは、ファイナライザ・サイクルを解放することはできませんがあります。代わりに、これらのオブジェクトはリサイクルできないごみのグローバルリストに追加されます。プログラムは、常にこの問題を回避するために再記述する必要があります。最後の手段として、プログラムは、このグローバルリストを読み込むことができ、有意義な方法で現在のアプリケーションのためにループ内でこれらの参照を解放します。

どのような価格で?

一部の人が言うように、太陽の下にはフリーランチはありません。しかし、ガベージコレクションのこの形式は、比較的安価です。各コンテナオブジェクトあたりの最大コストの一つは、三つの言葉の追加のメモリ空間を必要とします。メンテナンスオーバーヘッドコンテナコレクションがあります。ガベージコレクタの現在のバージョンでは、コストはおそらくパーセント減少し4のpybenchこのレートに基づいています。

ガベージコレクタ現在のレコード情報オブジェクトの三世代。パラメータを調整することにより、ガベージコレクションに費やされる時間は、それがどのように小さく、どのように小さな考えることができます。一部のアプリケーションでは、自動ガベージコレクションと、実行時の明示的な呼び出しをオフターンが大きくなることがあります。ただし、デフォルトのガベージコレクションのパラメータはpybench、見栄えしない過ごしたガベージコレクションの時間を実行します。明らかに、コンテナオブジェクトを分配する多数のアプリケーションは、より多くのガベージコレクション時間を引き起こす可能性があります。

現在のパッチは、ガベージコレクタを有効にするには、新しいコンフィギュレーションキーが追加されます。標準のPythonのPythonでのガベージコレクタはバイナリ互換性があるがあります。このオプションがオフの場合、作業Pythonインタプリタは効果がありません。

どのように私はそれを使用することができますか?

ちょうどそれでPythonの現在のバージョンをダウンロードしてください。ガベージコレクタは、将来のバージョン2.0に含まれており、デフォルトでは、デフォルトで有効になっています。あなたは、Python 1.5.2バージョンを使用している場合は、パッチワークのおそらく古いバージョンがあります。あなたは、Windowsプラットフォームを使用している場合は、交換するpython15.dllをダウンロードすることができます。

ベーム - デマーズ保守的なガベージコレクション

このパッチは、保守的なガベージコレクタベーム - デマーズを使用して、Pythonの1.5.2にいくつかの変更を追加します。しかし、あなたは、このパッチをヒットする必要があります。それでも、参照カウントを使用しています。ガベージコレクタは、参照カウントメモリ(すなわち、循環参照)解放されない解放します。これが最高のパフォーマンスでなければなりません。次のものが必要です。

$ cd Python-1.5.2
$ patch -p1 < ../gc-malloc-cleanup.diff
$ patch -p1 < ../gc-boehm.diff
$ autoconf
$ ./configure --with-gc

-lgcリンクオプションが用意されていながら、あなたはこのパッチlibgc.aをインストールすると仮定(は/ usr / local / libにはする必要があります)。あなたは、ダウンロードをコンパイルする前にこのライブラリを持っているし、インストールしない場合。

現在、このパッチはLinuxでのみテストされています。おそらく、また、他のUnixマシン上で動作します。私のLinuxマシンでは、PythonののGC版は、すべての回帰テストに合格します。

誰もが、リソースの収集を学ぶ非常に広いのpythonをお勧めし、ために私は、あなたへの書き込み入力する]をクリックし、共有の経験に学ぶ前に、上級プログラマがあり、研究ノート、ビジネス経験の可能性がある、と皆のために注意深くのpythonゼロを整理します細部を学ぶ実際のプロジェクトデータ、最新の技術上のあなたに、毎日のpython、見通しの根拠は、メッセージのままにしておく必要があり
要約を

その解決Pythonのメモリー管理およびガベージコレクションのアルゴリズムについては、この記事のためにすべてです

公開された43元の記事 ウォン称賛13 ビュー50000 +

おすすめ

転載: blog.csdn.net/haoxun11/article/details/105057229