Microsoft.Extensions.ObjectPoolを使ってみる
皆さん!!アロケーション、避けていますか!?
まぁ今日日、そこまでシビアになることも無いかもしれませんが、Microsoft.Extensions.ObjectPoolに関する記事があまり見当たらなかったので、備忘がてら記事にします。
基本的な使い方
where T : new()なオブジェクトであれば、これだけです。
※後述しますが、TがIDisposableの場合、少し注意が必要です。
生成・返却時に処理を挟みたい場合
PooledObjectPolicyを継承したクラスを作成します。
PooledObjectPolicyはIPooledObjectPolicyのabstract実装で、オブジェクトの生成・返却方針が記述されます。
WPFのTextBlockの場合(生成時に挟む)
TextBlockを再利用してみます。
ユースケースとしては、毎回同じ設定値がありつつ、一方でTextは変更したい、等でしょうか。
参考ソースは、行の仮想化をイメージしています。
CancellationTokenSourceの場合(返却時に挟む)
PooledObjectPolicy.Returnでfalseを返せば、返却されません。
標準で提供されているものを見てみる
DefaultObjectPoolProvider
- プロパティ
MaximumRetained
- 各ObjectPoolが保持するオブジェクトの数- デフォルトはプロセッサー数の2倍です
- メソッド
ObjectPool<T> Create<T>(IPooledObjectPolicy<T> policy);- 要求された
ObjectPool<T>のTに応じて、DisposableObjectPoolか、DefaultObjectPoolを生成し、返却します -
TがIDisposableな型である場合、DisposableObjectPoolが生成されます(そのままですね)
- 要求された
DefaultObjectPool<T>
DefaultObjectPool.cs
ObjectPool<T>の実装です。
えーっと、、、Tをプールします。
DisposableObjectPool<T>
DisposableObjectPool.cs
ObjectPool<T>の実装で、DefaultObjectPool<T>から派生します。
- 自身が
Disposeされた際に、手持ちのオブジェクトをすべてDisposeします - 自身が
Disposeされた以降に返却されたオブジェクトはすべてDisposeします
DefaultPooledObjectPolicy<T>
DefaultPooledObjectPolicy.cs
PooledObjectPolicyの実装です。
-
Create(生成ポリシー)は単にnew()するだけです -
Return(返却ポリシー)ではTがIResettableである場合、IResettable.TryResetを呼び出します。 - つまり
Tが自作タイプである場合、IResettableを実装しておけば、DefaultPooledObjectPolicy<T>が良い感じに処理してくれます
TがIDisposableな場合
前述しましたが、少し注意が必要です。
というのも、DefaultObjectPoolProvider<T>のところで触れた通り、プールの生成時にDisposableObjectPool<T>が返却されます。
このDisposableObjectPool<T>自身を破棄しない限り、中に抱えたオブジェクトは破棄されません。
ただ、ObjectPool<T>はIDisposableを実装していないため、以下のように書くことは出来ません。
こんな感じでチェックして破棄しても良いですが、、、
こういうのは、M.E.DIに任せておくと良いでしょう。
Discussion