C# 性能 - 热循环中指向 span 的指针

Yur*_*kii 2 c# performance loops slice bitconverter

我正在寻找BitConverter的更快替代方案:

但!在“热循环”内部:

//i_k_size = 8 bytes 
while (fs.Read(ba_buf, 0, ba_buf.Length) > 0 && dcm_buf_read_ctr < i_buf_reads)
{
    Span<byte> sp_data = ba_buf.AsSpan();
    for (int i = 0; i < ba_buf.Length; i += i_k_size)
    {
        UInt64 k = BitConverter.ToUInt64(sp_data.Slice(i, i_k_size));
    }
 }
Run Code Online (Sandbox Code Playgroud)

我将指针与转换集成的努力 - 使性能变得更糟。可以使用指针来使跨度更快

以下是基准测试:指针 2 数组快 2 倍

实际上我希望使用这段代码而不是 BitConverter:

public static int l_1gb = 1073741824;
static unsafe void Main(string[] args)
{
    Random rnd = new Random();
    Stopwatch sw1 = new();
    sw1.Start();
    byte[] k = new byte[8];

    fixed (byte* a2rr = &k[0])
    {
        for (int i = 0; i < 1000000000; i++)
        {
            rnd.NextBytes(k);
            //UInt64 p1 = BitConverter.ToUInt64(k); 
            //time: 10203.824
            //time: 10508.981
            //time: 10246.784
            //time: 10285.889

            //UInt64* uint64ptr = (UInt64*)a2rr;
            //x2 performance !
            UInt64 p2 = *(UInt64*)a2rr;

            //time: 4609.814
            //time: 4588.157
            //time: 4634.494
        }
    }
    Console.WriteLine($"time: {Math.Round(sw1.Elapsed.TotalMilliseconds, 3)}");
}
Run Code Online (Sandbox Code Playgroud)

Bli*_*ndy 5

假设ba_buf是 a byte[],运行循环的一种非常简单有效的方法如下:

foreach(var value in MemoryMarshal.Cast<byte, ulong>(ba_buf))
   // work with value here 
Run Code Online (Sandbox Code Playgroud)

如果您需要巧妙地处理缓冲区(例如,切除其中的一部分),AsSpan(start, count)请先使用它。

  • 不需要意见,可以【直接查看代码】(https://sharplab.io/#v2:EYLgxg9gTgpgtADwGwBYA0AXEBDAzgWwB8ABAJgEYBYAKGIAYACY8gOgCUBXAOwwEt8YLAJI8YUCAAcAymIBuvMDFwBuGjWIBmJqQYBhBjQDeNBqaZaOAGwhcA5g wCyACjYxsAEwDyXSwE8pEthcADzAvhgwaAHwM7tgY2ACUJmbG1GbpDLLYUAy4HPgMALwMdACqADKqaRmmAGbQbmAAFk5ZOVmWHDAMvFyOMPjQvg7ZuE3Yliy6eBih4TBoDFY2tpFOsfEJSdU16XkFANTFHV1 Vu0wA7Ln5Z2YAvjR3QA==)。这已经是最快的了。任何其他性能问题都来自于可疑的决策,例如对非常大的文件使用流,尤其是在读取量很小的情况下。 (2认同)