.NET 5で追加されたSystem.Runtime.InteropServices.CollectionsMarshal.AsSpanを使えば、高速にデータをなめることができるのではないかと思い速度を測ってみることにしました。
ひとまず単純なループ文にて、ListとAsSpanでどれほど速度に違いがあるのかを見てみる。
foreach (var value in list)
{
var name = value;
}
foreach (var value in CollectionsMarshal.AsSpan(_list))
{
var name = value;
}
ランダムな文字列を1~100文字含む文字列型を100回ループを回した結果、
AsSpanでループ文を回した場合の方が約200ns早かった。
平均値 | |
List | 270.05 ns |
AsSpan | 52.41 ns |
上記の結果から LINQ を使わずにforeachやfor文でループをする場面は AsSpan で Span 構造体 に変換するほうが速そうではある。
ただ、Stopwatch クラスで速度を測った際は ListもAsSpan もほぼ同じ速度であったため、やや気になる。
BenchmarkDotNet
今回ベンチマーク測定に使用したのはBenchmarkDotNetというライブラリ。
単純に Stopwatch クラスで計測するよりも数値の信用性が高くウォームアップ、GC、JITの影響、メモリ計測を吸収して計測してくれます。
手動で数回動かして、平均値の計算をするなどといったことが自動化されるため楽ですね。
// Program.cs
static void Main(string[] args)
{
BenchmarkRunner.Run<Measurement>();
}
// Measurement.cs
public Measurement()
{
...初期化コード
}
// ベンチマークの対象に属性を付与
[Benchmark]
public void LoopList()
{
foreach (var value in (list))
{
var name = value;
}
}
csvファイルで結果を出力してくれるため確認もしやすいですね。