ホームページ  >  記事  >  バックエンド開発  >  最新のオープンソース: 効率的な Python ユニバーサル オブジェクト プーリング ライブラリ

最新のオープンソース: 効率的な Python ユニバーサル オブジェクト プーリング ライブラリ

王林
王林転載
2023-04-17 09:04:021313ブラウズ

最新のオープンソース: 効率的な Python ユニバーサル オブジェクト プーリング ライブラリ

プログラミングでは、オブジェクト モジュールの作成は主にオブジェクトを生成することによって実現されます。オブジェクトは使用されると不要なモジュールとなり破棄されます。

システム内でオブジェクトを生成および破棄するプロセスでは、メモリの消費量が大幅に増加すると同時に、オブジェクトの破棄により情報が残留することが多く、問題が発生します。メモリリークのこと。

実際のプログラム開発プロセスでは、多数の重複オブジェクトの生成と破棄が必要になることがよくあります。そのため、メモリ リークによって生成された情報が大量になり、システムで再利用できなくなります。生成されたオブジェクトが多すぎると、どのモジュールをインスタンス化して実装するかを判断できなくなり、システムに負担がかかり、管理やその後の運用に支障をきたします。このように、最終的にはプログラムの速度が低下したり、クラッシュしたりする可能性があります。

オブジェクトプールとは、作成したオブジェクトをまとめて格納するプールで、オブジェクトを維持するための構造です。プログラムでオブジェクトを使用する必要がある場合、新しいオブジェクトをインスタンス化する代わりに、プールから直接オブジェクトを取得できます。

プログラミングのプロセスでは、ほとんどの人はオブジェクトの使用と効果の実現のみに焦点を当てる傾向があります。実際には、作成と使用の間に初期化プロセスがありますが、システムは2 つの作成ステップが組み合わされるため、設計者はシステム上のオブジェクトの作成と破棄による影響を無視できます。

一般に、オブジェクトの作成と破棄にかかるコストは非常に小さいため無視できますが、プログラムでオブジェクトの複数の作成が含まれ、作成時間が比較的長い場合は、システム速度が消費のこの部分によって制限されていることが明らかに感じられます。

オブジェクト プールは、GC 圧力を軽減するための推奨される方法とみなされ、最も簡単な方法でもあります。

オブジェクト プール モードは、主に次のアプリケーション シナリオに適しています:

  • リソースが制限されたシナリオ。例えば、スケーラビリティを必要としない環境(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 サイトの他の関連記事を参照してください。

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