ホームページ  >  記事  >  バックエンド開発  >  効率的な Python ユニバーサル オブジェクト プーリング ライブラリの使用方法

効率的な Python ユニバーサル オブジェクト プーリング ライブラリの使用方法

WBOY
WBOY転載
2023-05-11 16:16:06852ブラウズ

オブジェクト プール モードは、主に次のアプリケーション シナリオに適しています:
  • リソースが限られたシナリオ。例えば、スケーラビリティを必要としない環境(CPUやメモリなどの物理リソースが限られている)では、CPUの性能が十分ではなく、メモリも比較的逼迫しているため、ガベージコレクションやメモリジッタの影響が比較的大きくなります。メモリ管理の効率を改善する必要がある、スループットよりも応答性が良い、量が重要である。

  • #メモリ内のオブジェクトの数は限られています。


  • #作成に費用がかかるオブジェクト。

  • 有効期間が短く初期化コストが低い多数のオブジェクトをプールして、メモリ割り当てと再割り当てコストを削減し、メモリの断片化を回避します。

  • Python のような動的言語では、GC は参照テクノロジに依存して、オブジェクトが時期尚早にリサイクルされないようにします。アイドル期間が使用されると、オブジェクトがリサイクルされます。保管のためにオブジェクト プールに委任できます。

  • Pond の概要


Pond は、優れたパフォーマンス、少ないメモリ使用量、高いヒット率という特徴を備えた、Python の効率的な汎用オブジェクト プールです。 . .おおよその統計に基づく頻度に基づいて自動的にリサイクルする機能により、各オブジェクト プール内の空きオブジェクトの数を自動的に調整できます。


現在の Python には、完全なテスト ケース、完全なコード コメント、および完全なドキュメントを備えた、これより優れたオブジェクト プーリング ライブラリがないため、同時に、現在の主流のオブジェクト プーリング ライブラリには、比較的インテリジェントなオブジェクト プーリング ライブラリがありません。自動リサイクル機構。


Pond は、コミュニティによって公開された完全なテスト ケース、90% 以上のカバー率、完全なコード コメント、完全なドキュメントを備えた Python の最初のオブジェクト プーリング ライブラリである可能性があります。


Pond は、Apache Commons Pool、Netty Recycler、HikariCP、Caffeine からインスピレーションを受けており、多くの利点を組み合わせています。


第二に、Pond は非常に小さなメモリ空間内の各オブジェクト プールの使用頻度を近似カウントを使用してカウントし、自動的にリサイクルします。


トラフィックが比較的ランダムで平均的な場合、デフォルトのポリシーと重みによりメモリ使用量を 48.85% 削減でき、借用ヒット率は 100% になります。


効率的な Python ユニバーサル オブジェクト プーリング ライブラリの使用方法 トラフィックが 2/8 の法則と比較的一致している場合、デフォルトのポリシーと重みによりメモリ使用量を 45.7% 削減でき、ボロー ヒット率は次のようになります。 100%。


効率的な Python ユニバーサル オブジェクト プーリング ライブラリの使用方法設計の概要


Pond は主に、FactoryDict、Counter、PooledObjectTree、および別個のリサイクル スレッドの 3 つの部分で構成されています。


FactoryDict


Pond を使用するには、オブジェクト ファクトリ PooledObjectFactory を実装する必要があります。PooledObjectFactory は、オブジェクトの作成、初期化、破棄、検証などの操作を提供し、Pond によって呼び出されます。


したがって、オブジェクト プールが完全に異なるオブジェクトの保存をサポートするために、Pond は辞書を使用して、各ファクトリ クラスの名前と、それが実装するファクトリ クラスのインスタンス化されたオブジェクトを記録します。


各 PooledObjectFactory には、オブジェクトの作成、オブジェクトの破棄、オブジェクトがまだ使用可能かどうかの確認、およびオブジェクトのリセットという 4 つの機能が必要です。


特別なのは、Pond がオブジェクトの自動リセットをサポートしていることです。これは、シナリオによっては、最初にオブジェクトに値を割り当てて渡し、渡された後にリサイクルする必要がある状況があるためです。汚染を避けるため、この機能を推奨します。この機能はさまざまなシーンで実現できます。


Counter


Counter には、おおよそのカウンタが保存されます。


PooledObjectTree


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 サイトの他の関連記事を参照してください。

声明:
この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。