ネットパフォーマンスチューニング - ArrayPool 詳細
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)
rent 配列が返す実際の長さは,要求された長さよりも大きい可能性があり,返す長さの1つは
Return
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
関連
-
NET6新機能 - 暗黙の名前空間参照
-
NET6新機能 新構造体の最適化
-
ASP.NET CoreでCAPの取引詳細を自動で有効にする
-
swagger uiをasp.net coreに統合する原理
-
ASP.NET Core MVC Dependency Injection ビューとコントローラ
-
認証プロセスの記録にjwtを使用したネット
-
ASP.NET Coreで複数のサービス実装クラスをインジェクトする方法
-
ajaxでポップアップアラートボックス
-
CS0234 名前空間 'Microsoft.AspNet' に型または名前空間名 'Mvc' が存在しない (あなたは
-
ASP.NETでのRadioButton(ラジオボタン)の使用について
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
.NET複数データベース一括データ挿入、更新(SqlServer、MySql、PgSql、Oracleをサポートします。)
-
.NET Coreでオブジェクトプールを使用する
-
ASP.NET CoreでURLを設定する5つの方法
-
30分でわかるコング経由の.NETゲートウェイ
-
net core downlink tracking skywalking インストールと使いやすいチュートリアル
-
ネットのメモリ管理に関する5つの基本
-
ASP.NET Coreミドルウェアによるグローバル例外処理機構の利用について
-
NET 6 の今後の新機能 暗黙の名前空間参照
-
Net CoreによるAutoFacの利用
-
名前 'xxx' が現在のコンテキストに存在しない エラー解決方法の1つ