♻️

Microsoft.Extensions.ObjectPoolを使ってみる

2023/12/24に公開

皆さん!!アロケーション、避けていますか!?

まぁ今日日、そこまでシビアになることも無いかもしれませんが、Microsoft.Extensions.ObjectPoolに関する記事があまり見当たらなかったので、備忘がてら記事にします。

基本的な使い方

where T : new()なオブジェクトであれば、これだけです。
※後述しますが、TIDisposableの場合、少し注意が必要です。
https://github.com/kk-river/Articles/blob/main/src/TryObjectPool/BasicUsage.cs#L7-L16

生成・返却時に処理を挟みたい場合

PooledObjectPolicyを継承したクラスを作成します。
PooledObjectPolicyIPooledObjectPolicyabstract実装で、オブジェクトの生成・返却方針が記述されます。

WPFのTextBlockの場合(生成時に挟む)

TextBlockを再利用してみます。
ユースケースとしては、毎回同じ設定値がありつつ、一方でTextは変更したい、等でしょうか。
参考ソースは、行の仮想化をイメージしています。
https://github.com/kk-river/Articles/blob/main/src/TryObjectPool/WithTextBlock.cs#L8-L61

CancellationTokenSourceの場合(返却時に挟む)

PooledObjectPolicy.Returnでfalseを返せば、返却されません。
https://github.com/kk-river/Articles/blob/main/src/TryObjectPool/WithCts.cs#L5-L29

標準で提供されているものを見てみる

DefaultObjectPoolProvider

DefaultObjectPoolProvider.cs

  • プロパティMaximumRetained
     - 各ObjectPoolが保持するオブジェクトの数
    • デフォルトはプロセッサー数の2倍です
  • メソッドObjectPool<T> Create<T>(IPooledObjectPolicy<T> policy);
    • 要求されたObjectPool<T>Tに応じて、DisposableObjectPoolか、DefaultObjectPoolを生成し、返却します
    • TIDisposableな型である場合、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(返却ポリシー)ではTIResettableである場合、IResettable.TryResetを呼び出します。
  • つまりTが自作タイプである場合、IResettableを実装しておけば、DefaultPooledObjectPolicy<T>が良い感じに処理してくれます

TIDisposableな場合

前述しましたが、少し注意が必要です。
というのも、DefaultObjectPoolProvider<T>のところで触れた通り、プールの生成時にDisposableObjectPool<T>が返却されます。
このDisposableObjectPool<T>自身を破棄しない限り、中に抱えたオブジェクトは破棄されません。
ただ、ObjectPool<T>IDisposableを実装していないため、以下のように書くことは出来ません。
https://github.com/kk-river/Articles/blob/main/src/TryObjectPool/NoteOfIDisposable.cs#L8-L18

こんな感じでチェックして破棄しても良いですが、、、
https://github.com/kk-river/Articles/blob/main/src/TryObjectPool/NoteOfIDisposable.cs#L20-L29

こういうのは、M.E.DIに任せておくと良いでしょう。
https://github.com/kk-river/Articles/blob/main/src/TryObjectPool/NoteOfIDisposable.cs#L31-L51

GitHubで編集を提案

Discussion