.net 5におけるbyte*,nuint,longベースのポインタオフセットメモリアクセス性能テスト


テスト環境

  • SDK:5.0.100-preview.7.20366.6
  • CPU:Intel Core i7 - 6700
  • Any CPU
  • Release

  • 初期化テスト

    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は頭がいい