問題タブ [benchmarkdotnet]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c# - Newtonsoft.Json デシリアライゼーションのベンチマーク: ストリームおよび文字列から
Newtonsoft.Jsonを使用して HTTP 応答 JSON ペイロードを逆シリアル化する 2 つのアプローチのパフォーマンス (速度、メモリ使用量) の比較に興味があります。
ストリームを使用するためのNewtonsoft.Json の Performance Tipsは知っていますが、もっと知りたいと思っていました。BenchmarkDotNetを使用して簡単なベンチマークを作成しましたが、結果に少し困惑しています (以下の数値を参照)。
私が得たもの:
- ストリームからの解析は常に高速ですが、それほど多くはありません
- 文字列を入力として使用すると、小規模および「中規模」の JSON を解析すると、より良いまたは同等のメモリ使用量になります。
- メモリ使用量の大きな違いは、大規模な JSON で見られ始めます (文字列自体が LOH になる)。
(まだ) 適切なプロファイリングを行う時間がありませんでした。(エラーがない場合) ストリーム アプローチのメモリ オーバーヘッドに少し驚いています。コード全体はこちらです。
?
- 私のアプローチは正しいですか?(使用法
MemoryStream
; シミュレートHttpResponseMessage
とその内容; ...) - ベンチマーク コードに問題はありますか?
- なぜこのような結果が表示されるのですか?
ベンチマークの設定
MemoryStream
ベンチマークの実行中に何度も使用する準備をしています:
ストリームの逆シリアル化
文字列の逆シリアル化
最初に JSON をストリームから文字列に読み取り、次に逆シリアル化を実行します。別の文字列が割り当てられた後、逆シリアル化に使用されます。
一般的な方法
結果
小さな JSON
10000回繰り返し
- ストリーム: 平均 25.69 ミリ秒、61.34 MB 割り当て
- 文字列: 平均 31.22 ミリ秒、割り当てられた 36.01 MB
ミディアム JSON
1000回繰り返し
- ストリーム: 平均 24.07 ミリ秒、12 MB 割り当て
- 文字列: 平均 25.09 ミリ秒、割り当てられた 12.85 MB
大きな JSON
100回繰り返した
- ストリーム: 平均 229.6 ミリ秒、47.54 MB 割り当て、オブジェクトは Gen 1 に到達
- 文字列: 平均 240.8 ミリ秒、割り当てられた 92.42 MB、オブジェクトが Gen 2 に到達しました!
アップデート
のソースを調べたところ、 JsonConvert:816から逆シリアル化するときにwith をJsonConvert
内部的に使用していることがわかりました。ストリームもそこに関与しています (もちろん!)。JsonTextReader
StringReader
string
次に、それ自体をさらに掘り下げることにしましたStreamReader
が、一目惚れしました-常に配列 buffer ( byte[]
): StreamReader:244を割り当てています。これは、そのメモリ使用を説明しています。
これで「なぜ」の答えが得られます。解決策は簡単です。インスタンス化するときに小さいバッファ サイズを使用します。StreamReader
最小バッファ サイズのデフォルトは 128 ですが (「参考文献」を参照StreamReader.MinBufferSize
)、任意の値を指定できます> 0
(ctor オーバーロードの 1 つを確認してください)。
もちろん、バッファサイズはデータの処理に影響します。次に使用する必要があるバッファ サイズに答えると、依存します。より小さな JSON 応答が予想される場合は、小さなバッファーに固執するのが安全だと思います。
azure-devops - Azure Pipeline 内で BenchmarkDotNet ベンチマークを実行する
Azure DevOps パイプライン内で BenchmarkDotNet で作成されたベンチマークを実行しようとしています。これは私が問題を抱えているビルドです。ベンチマークの実行ステップを見てください。ご覧のとおり、ベンチマークを使用したすべてのテストに合格しましたが、実際には実行されたベンチマークはありません。ログからのメッセージ:
ベンチマークを使用してクラスに属性を追加InProcess
すると、ベンチマークが実行されます。しかし、私のベンチマークの一部は長時間実行されているため、プロセス外のベンチマークを使用することを推奨する BenchmarkDotNet によって中断されます。
Azure パイプライン内でアウト プロセス ベンチマークを実行するにはどうすればよいですか?