.net 5におけるbyte*,nuint,longベースのポインタオフセットメモリアクセス性能テスト
19061 ワード
テスト環境
初期化テスト
var sw = new Stopwatch();//
var data = ((nuint)4).Allocate();//
data.Write(3, (byte)1);//
data.Write(2, (byte)3);
data.Write(1, (byte)0);
data.Write(0, (byte)0);
var c = 0;//
jitの初回運転の遅い影響結果を避けるために,
while(true)
回以上のテストを用いた.byte*オフセットテスト
//byte*
c = 0;
var p = (byte*)data;
Console.WriteLine("byte*");
sw.Restart();
for (int i = 0; i < 1000000000; i++)
{
c += p[3];
c += p[2];
c += p[1];
c += p[0];
}
Console.WriteLine(sw.ElapsedMilliseconds);
Console.WriteLine(c);
nuintオフセット+インライン関数テスト
// nuint
c = 0;
Console.WriteLine("M");
sw.Restart();
for (int i = 0; i < 1000000000; i++)
{
c += data.Read<byte>(3);
c += data.Read<byte>(2);
c += data.Read<byte>(1);
c += data.Read<byte>(0);
}
Console.WriteLine(sw.ElapsedMilliseconds);
Console.WriteLine(c);
そのうち
Read
は以下のように実現される.[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T Read<T>(this nuint ptr, nint offset) where T : unmanaged
{
return *(T*)((nint)ptr + offset);
}
nuintオフセットテスト
//nuint
c = 0;
Console.WriteLine("nuint");
sw.Restart();
for (int i = 0; i < 1000000000; i++)
{
c += *(byte*)(data + 3);
c += *(byte*)(data + 2);
c += *(byte*)(data + 1);
c += *(byte*)(data + 0);
}
Console.WriteLine(sw.ElapsedMilliseconds);
Console.WriteLine(c);
longオフセットテスト
//long
c = 0;
p = (byte*)data;
Console.WriteLine("long");
sw.Restart();
for (int i = 0; i < 1000000000; i++)
{
c += *(byte*)((long)p + 3);
c += *(byte*)((long)p + 2);
c += *(byte*)((long)p + 1);
c += *(byte*)((long)p + 0);
}
Console.WriteLine(sw.ElapsedMilliseconds);
Console.WriteLine(c);
結果
すべての試験用時間は1100 ms程度であり、明らかな差はなかった.
RyuJITは頭がいい