ホームページ >バックエンド開発 >Python チュートリアル >最新のオープンソース: 効率的な Python ユニバーサル オブジェクト プーリング ライブラリ
プログラミングでは、オブジェクト モジュールの作成は主にオブジェクトを生成することによって実現されます。オブジェクトは使用されると不要なモジュールとなり破棄されます。
システム内でオブジェクトを生成および破棄するプロセスでは、メモリの消費量が大幅に増加すると同時に、オブジェクトの破棄により情報が残留することが多く、問題が発生します。メモリリークのこと。
実際のプログラム開発プロセスでは、多数の重複オブジェクトの生成と破棄が必要になることがよくあります。そのため、メモリ リークによって生成された情報が大量になり、システムで再利用できなくなります。生成されたオブジェクトが多すぎると、どのモジュールをインスタンス化して実装するかを判断できなくなり、システムに負担がかかり、管理やその後の運用に支障をきたします。このように、最終的にはプログラムの速度が低下したり、クラッシュしたりする可能性があります。
オブジェクトプールとは、作成したオブジェクトをまとめて格納するプールで、オブジェクトを維持するための構造です。プログラムでオブジェクトを使用する必要がある場合、新しいオブジェクトをインスタンス化する代わりに、プールから直接オブジェクトを取得できます。
プログラミングのプロセスでは、ほとんどの人はオブジェクトの使用と効果の実現のみに焦点を当てる傾向があります。実際には、作成と使用の間に初期化プロセスがありますが、システムは2 つの作成ステップが組み合わされるため、設計者はシステム上のオブジェクトの作成と破棄による影響を無視できます。
一般に、オブジェクトの作成と破棄にかかるコストは非常に小さいため無視できますが、プログラムでオブジェクトの複数の作成が含まれ、作成時間が比較的長い場合は、システム速度が消費のこの部分によって制限されていることが明らかに感じられます。
オブジェクト プールは、GC 圧力を軽減するための推奨される方法とみなされ、最も簡単な方法でもあります。
Pond は、優れたパフォーマンス、少ないメモリ使用量、高いヒット率という特徴を備えた、Python の効率的な汎用オブジェクト プールです。おおよその統計に基づく頻度に基づいて自動的にリサイクルする機能により、各オブジェクト プール内の空きオブジェクトの数を自動的に調整できます。
現在の Python には、完全なテスト ケース、完全なコード コメント、および完全なドキュメントを備えた、これより優れたオブジェクト プーリング ライブラリがないため、同時に、現在の主流のオブジェクト プーリング ライブラリには、比較的インテリジェントなオブジェクト プーリング ライブラリがありません。自動リサイクル機構。
Pond は、コミュニティによって公開された完全なテスト ケース、90% 以上のカバー率、完全なコード コメント、完全なドキュメントを備えた Python の最初のオブジェクト プーリング ライブラリである可能性があります。
Pond は、Apache Commons Pool、Netty Recycler、HikariCP、Caffeine からインスピレーションを受けており、多くの利点を組み合わせています。
第二に、Pond は非常に小さなメモリ空間内の各オブジェクト プールの使用頻度を近似カウントを使用してカウントし、自動的にリサイクルします。
トラフィックが比較的ランダムで平均的な場合、デフォルトのポリシーと重みによりメモリ使用量を 48.85% 削減でき、借用ヒット率は 100% になります。
トラフィックが 2/8 の法則と比較的一致している場合、デフォルトのポリシーと重みによりメモリ使用量を 45.7% 削減でき、ボロー ヒット率は次のようになります。 100%。
Pond は主に、FactoryDict、Counter、PooledObjectTree、および別個のリサイクル スレッドの 3 つの部分で構成されています。
Pond を使用するには、オブジェクト ファクトリ PooledObjectFactory を実装する必要があります。PooledObjectFactory は、オブジェクトの作成、初期化、破棄、検証などの操作を提供し、Pond によって呼び出されます。
したがって、オブジェクト プールが完全に異なるオブジェクトの保存をサポートするために、Pond は辞書を使用して、各ファクトリ クラスの名前と、それが実装するファクトリ クラスのインスタンス化されたオブジェクトを記録します。
各 PooledObjectFactory には、オブジェクトの作成、オブジェクトの破棄、オブジェクトがまだ使用可能かどうかの確認、およびオブジェクトのリセットという 4 つの機能が必要です。
特別なのは、Pond がオブジェクトの自動リセットをサポートしていることです。これは、シナリオによっては、最初にオブジェクトに値を割り当てて渡し、渡された後にリサイクルする必要がある状況があるためです。汚染を避けるため、この機能を推奨します。この機能はさまざまなシーンで実現できます。
Counter には、おおよそのカウンタが保存されます。
PooleedObjectTree は辞書です。各キーは先入れ先出しキューに対応します。これらのキューはスレッドセーフです。
各キューは複数の PooleedObject を保持します。 PooledObject は、作成時間、最後の貸出時間、および実際に必要なオブジェクトを保存します。
Pond の借用とリサイクルはどちらもスレッド セーフです。 Python のキュー モジュールは、マルチスレッド プログラミングに適した先入れ先出し (FIFO) データ構造を提供します。これを使用すると、プロデューサーとコンシューマーのスレッド間でメッセージやその他のデータを安全に受け渡すことができます。
ロックは呼び出し元によって処理され、すべての複数のスレッドが同じ Queue インスタンス上で安全かつ簡単に動作できます。 Pond の借用とリサイクルはどちらもキュー上で動作するため、基本的にスレッドセーフであると考えられます。
Pond を使用してオブジェクトを貸出する場合、まず、貸出したいオブジェクトのタイプが既に PooledObjectTree に存在するかどうかを確認します。このオブジェクトのオブジェクト プールが空かどうかを確認し、空の場合は新しいオブジェクト プールを作成します。
オブジェクト プールに過剰なオブジェクトがある場合は、キューを使用してオブジェクトをポップアップし、オブジェクトが使用可能かどうかを確認します。使用できない場合は、対応するファクトリが自動的に呼び出され、オブジェクトをクリーンにして破棄します。同時に、Python での GC カウントがクリアされるため、GC によってより速くリサイクルされ、次のオブジェクトが取得されます。利用できるようになるまで続けてください。
このオブジェクトが利用可能な場合は、直接返されます。もちろん、オブジェクトがオブジェクト プールから取り出される場合でも、新しいオブジェクトが作成される場合でも、Counter はカウントをインクリメントするために使用されます。
オブジェクトをリサイクルするとき、対象のオブジェクト プールが存在するかどうかを確認します。存在する場合は、オブジェクト プールがいっぱいかどうかを確認します。満杯の場合は自動的に破棄されます。返されるオブジェクト。
次に、オブジェクトの貸し出し時間が長すぎるかどうかをチェックし、設定された最大時間を超えた場合もクリアされます。
自動リサイクルは時々実行されます。デフォルトは 300 秒です。頻繁に使用されないオブジェクト プール内のオブジェクトを自動的にクリーンアップします。
最初に Pond ライブラリをインストールし、プロジェクト内でそれを参照できます。
pip install pondpond
from pond import Pond, PooledObjectFactory, PooledObject
まず、配置するオブジェクトのタイプのファクトリ クラスを宣言する必要があります。たとえば、次の例では、プールされたオブジェクトを Dog にしたいので、最初にPooledDogFactory クラスを作成し、PooledObjectFactory を実装します。
class Dog: name: str validate_result:bool = True class PooledDogFactory(PooledObjectFactory): def creatInstantce(self) -> PooledObject: dog = Dog() dog.name = "puppy" return PooledObject(dog) def destroy(self, pooled_object: PooledObject): del pooled_object def reset(self, pooled_object: PooledObject) -> PooledObject: pooled_object.keeped_object.name = "puppy" return pooled_object def validate(self, pooled_object: PooledObject) -> bool: return pooled_object.keeped_object.validate_result
次に、Pond オブジェクトを作成する必要があります:
pond = Pond(borrowed_timeout=2, time_between_eviction_runs=-1, thread_daemon=True, eviction_weight=0.8)
Pond は、次のことを表すいくつかのパラメータを渡すことができます:
borrowed_timeout: 単位は秒、借用オブジェクトの最大期間。この期間を超えたオブジェクトは返されたときに自動的に破棄され、オブジェクト プールには入れられません。
time_between_eviction_runs: 単位は秒で、自動リサイクルの間隔です。
thread_daemon: デーモン スレッド。True の場合、メイン スレッドが閉じられると、自動的にリサイクルされたスレッドも閉じられます。
eviction_weight: 自動リサイクル中の重み。この重みには最大使用頻度が乗算されます。使用頻度がこの値より低いオブジェクト プール内のオブジェクトは、クリーンアップ ステップに入ります。
ファクトリ クラスのインスタンス化:
factory = PooledDogFactory(pooled_maxsize=10, least_one=False)
PooledObjectFactory を継承するすべてのものには、pooled_maxsize パラメーターと minimum_one パラメーターを渡すことができる独自のコンストラクターがあります。
pooled_maxsize: このファクトリ クラスによって生成されたオブジェクト プールに配置できるオブジェクトの最大数。
least_one: True の場合、自動クリーンアップを開始すると、このファクトリ クラスによって生成されたオブジェクトのオブジェクト プールに少なくとも 1 つのオブジェクトが保持されます。
このファクトリ オブジェクトを Pond に登録します。デフォルトでは、ファクトリのクラス名が PooledObjectTree のキーとして使用されます:
pond.register(factory)
もちろん、次のようにすることもできます。名前は次のようになります。 PooledObjectTree のキーとして:
pond.register(factory, name="PuppyFactory")
登録が成功すると、Pond はオブジェクト プールがいっぱいになるまで、ファクトリで設定された pooled_maxsize に従ってオブジェクトの作成を自動的に開始します。
オブジェクトの借用と返却:
pooled_object: PooledObject = pond.borrow(factory) dog: Dog = pooled_object.use() pond.recycle(pooled_object, factory)
もちろん、オブジェクトを名前で借用したり返却したりできます:
pooled_object: PooledObject = pond.borrow(name="PuppyFactory") dog: Dog = pooled_object.use() pond.recycle(pooled_object, name="PuppyFactory")
オブジェクト プールを完全にクリーンアップします:
pond.clear(factory)
名前でオブジェクト プールをクリーンアップします:
pond.clear(name="PuppyFactory")
通常の状況では、上記の方法を使用するだけで済み、オブジェクトの生成とリサイクルは完全に自動で行われます。
以上が最新のオープンソース: 効率的な Python ユニバーサル オブジェクト プーリング ライブラリの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。