1. ホーム
  2. Web プログラミング
  3. ASP.NET

ネットパフォーマンスチューニング - ArrayPool 詳細

2022-01-14 14:40:18

1. 使用方法

  • バッファプールインスタンスの取得
    Create / Shared var pool=ArrayPool[byte].
    
  • バッファプールインスタンスを呼び出します。 Rent() バッファ領域貸出機能
     byte[] array=pool.Rent(1024)
    
  • バッファプールインスタンスを呼び出します。 Return(array[T]) 借りた領域を返す関数 pool.Return(array)

2. 共有

Shared は静的な共有インスタンスを返しますが、これは実際には

 TlsOverPerCoreLockedStacksArrayPool
internal sealed class TlsOverPerCoreLockedStacksArrayPool<T> : ArrayPool<T>
{ private
    private static readonly TlsOverPerCoreLockedStacksArrayPool<T> s_shared = new TlsOverPerCoreLockedStacksArrayPool<T>();

    public static ArrayPool<T> Shared => s_shared;
}

 2^20( 1024*1024 = 1 048 576), the

2.1 特徴

レンタルされた配列の長さは,以下のとおりです。 Rent さもなければ、GCからメモリ空間が再開されます。
(16*2^n)
Return
rent 配列が返す実際の長さは,要求された長さよりも大きい可能性があり,返す長さの1つは clearArray バッファを返すとき、設定されていない場合 private static void TimeMonitor() { //generate a random array of 3000 length values var sizes = new int[30000]; Parallel.For(0, 10000, x => { sizes[x] = new Random().Next(1024 * 800, 1024 * 1024); }); // Buffer pool way to rent arrays var gcAllocate0 = GC.GetTotalAllocatedBytes(); var watch = new Stopwatch(); Console.WriteLine("start"); watch.Start(); for (int i = 0; i < 10000; i++) { //CreateArrayByPool(ArrayPool<int>.Shared, 1024 * 1024,sizes[i], false); var arr = ArrayPool<int>.Shared.Rent(sizes[i]); for (int j = 0; j < sizes[i]; j++) { arr[j] = i; } ArrayPool<int>.Shared.Return(arr, true); } var time1 = watch.ElapsedMilliseconds; var gcAllocate1 = GC.GetTotalAllocatedBytes(true); //new way to allocate array space watch.Restart(); for (int i = 0; i < 30000; i++) { //CreateArrayDefault(i, sizes[i], false); var arr = new int[sizes[i]]; for (int j = 0; j < sizes[i]; j++) { arr[j] = i; } } var time2 = watch.ElapsedMilliseconds; var gcAllocate2 = GC.GetTotalAllocatedBytes(true); Console.WriteLine("ArrayPool method of creating arrays takes time:" + time1 + " GcTotalAllocatedBytes" + (gcAllocate1 - gcAllocate0)); Console.WriteLine("Default way to create arrays: " + time2 + " GcTotalAllocate" + (gcAllocate2 - gcAllocate1 - gcAllocate0)); } の場合、次の賃借人は、前に充填された値を見ることができます(返された配列が、次の賃借人が要求した長さにちょうどなるときに見られることになります)。
バッファプールのメモリ解放はリアルタイムではなく、10~20秒程度でバッファが空いた時点で第2世代GCで一括解放されます
同時実行数が増え続けると、バッファプールが占有するメモリ容量も増え続け、上限はないようです

2.2 時間消費量の比較

private static void PostFileByByBytesPool(FormFile file)
{
    HttpClient client = new HttpClient() { BaseAddress = new Uri("https://fileserver.com") }

    var fileLen = (int)file.Length;
    var fileArr = ArrayPool<byte>.Shared.Rent(fileLen);

    using var stream = file.OpenReadStream();
    stream.Read(fileArr, 0, fileLen);

    MultipartFormDataContent content = new MultipartFormDataContent();
    content.Add(new ByteArrayContent(fileArr, 0, fileLen), "id_" + Guid.NewGuid().ToString(), file.FileName);

    client.PostAsync("/myfile/" + file.FileName, content).Wait();
    ArrayPool<byte>.Shared.Return(fileArr, true);
}



メモリ使用量のスクリーンショット:左側の変動のない水平線がバッファプール実行のプロセス、右側が手動で配列を作成する実行のプロセス

実行結果です。

ArrayPoolメソッドによる配列の作成に時間がかかりました。17545 Gc 総割り当て量 4130800
配列を作成するデフォルトの方法:26870 Gc 総割り当て量 37354100896

2.3 例 (フロントエンドのファイルアップロード OSS をバックエンドの Api 経由で行う場合)

ArrayPool 

3. 作成()

Create() ConfigurableArrayPool 関数は ConfigurableArrayPool オブジェクト

1024*1024*1024 コンストラクタは2つの引数を取ります。

  • maxArrayLength。 1回のレンタルで使用できる配列の最大長で、これを超えないこと
     Shared 
    
  • maxArraysPerBucket. 未返却のバッファが存在しうる最大数

この2つのパラメータで // Create a custom buffer pool instance with a maximum length of 1024 * 2048 for a single array and a maximum of 10 buffers that can be rented at the same time ArrayPool<int> CustomerArrayPool = ArrayPool<int>.Create(1024 * 2048,10); という2つの問題があります。

  • 大きなファイルなどを保存するために、1つの配列の最大長をカスタマイズして、より多くのメモリ領域を得ることができます。
  • 配列の長さとバッファの最大数を制限することで、回復不能なメモリの最大量を制限し、高い並行処理時にバッファプールが継続的に増大することを防止します


CustomerArrayPool=Null 

Sharedとは異なり Keep the CustomerArrayPool の場合、このバッファプールが占有しているメモリは、次のガベージコレクションで直ちに解放されます。

予測不可能なリスクを回避するために The CustomerArrayPool を存続させる。

また、メモリの不正使用を防ぐために、以下のように制限する必要があります。 ArrayPool の数が増えています。

ネットパフォーマンスのチューニング Net performance tuning - ArrayPool Net performance tuning - {{code ArrayPool ネットパフォーマンスチューニング ArrayPool