Microsoft.Extensions.ObjectPoolを使ってみる
皆さん!!アロケーション、避けていますか!?
まぁ今日日、そこまでシビアになることも無いかもしれませんが、Microsoft.Extensions.ObjectPool
に関する記事があまり見当たらなかったので、備忘がてら記事にします。
基本的な使い方
where T : new()
なオブジェクトであれば、これだけです。
※後述しますが、T
がIDisposable
の場合、少し注意が必要です。
生成・返却時に処理を挟みたい場合
PooledObjectPolicy
を継承したクラスを作成します。
PooledObjectPolicy
はIPooledObjectPolicy
のabstract
実装で、オブジェクトの生成・返却方針が記述されます。
TextBlock
の場合(生成時に挟む)
WPFの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