Fastest way of reading and writing binary

前端 未结 4 799
渐次进展
渐次进展 2021-01-31 06:42

I\'m currently optimizing an application, one of the operations that is done very often is reading and writing binary. I need 2 types of functions:

Set(byte[] ta         


        
4条回答
  •  半阙折子戏
    2021-01-31 07:06

    Important: if you only need the one endian, see the pointer magic by wj32 / dtb


    Personally, I would be writing directly to a Stream (perhaps with some buffering), and re-using a shared buffer that I can generally assume is clean. Then you can make some shortcuts and assume index 0/1/2/3.

    Certainly don't use BitConverter, as that can't be used for both little/big-endian, which you require. I would also be inclined to just use bit-shifting rather than unsafe etc. It is actally the fastest, based on the following (so I'm glad that this is how I already do it my code here, look for EncodeInt32Fixed):

    Set1: 371ms
    Set2: 171ms
    Set3: 993ms
    Set4: 91ms <==== bit-shifting ;-p
    

    code:

    using System;
    using System.Diagnostics;
    using System.Runtime.InteropServices;
    static class Program
    {
        static void Main()
        {
            const int LOOP = 10000000, INDEX = 100, VALUE = 512;
            byte[] buffer = new byte[1024];
            Stopwatch watch;
    
            watch = Stopwatch.StartNew();
            for (int i = 0; i < LOOP; i++)
            {
                Set1(buffer, INDEX, VALUE);
            }
            watch.Stop();
            Console.WriteLine("Set1: " + watch.ElapsedMilliseconds + "ms");
    
            watch = Stopwatch.StartNew();
            for (int i = 0; i < LOOP; i++)
            {
                Set2(buffer, INDEX, VALUE);
            }
            watch.Stop();
            Console.WriteLine("Set2: " + watch.ElapsedMilliseconds + "ms");
    
            watch = Stopwatch.StartNew();
            for (int i = 0; i < LOOP; i++)
            {
                Set3(buffer, INDEX, VALUE);
            }
            watch.Stop();
            Console.WriteLine("Set3: " + watch.ElapsedMilliseconds + "ms");
    
            watch = Stopwatch.StartNew();
            for (int i = 0; i < LOOP; i++)
            {
                Set4(buffer, INDEX, VALUE);
            }
            watch.Stop();
            Console.WriteLine("Set4: " + watch.ElapsedMilliseconds + "ms");
    
            Console.WriteLine("done");
            Console.ReadLine();
        }
        unsafe static void Set1(byte[] target, int index, int value)
        {
            fixed (byte* p = &target[0])
            {
                Marshal.WriteInt32(new IntPtr(p), index, value);
            }
        }
    
        unsafe static void Set2(byte[] target, int index, int value)
        {
            int* p = &value;
            for (int i = 0; i < 4; i++)
            {
                target[index + i] = *((byte*)p + i);
            }
        }
    
        static void Set3(byte[] target, int index, int value)
        {
            byte[] data = BitConverter.GetBytes(value);
            Buffer.BlockCopy(data, 0, target, index, data.Length);
        }
        static void Set4(byte[] target, int index, int value)
        {
            target[index++] = (byte)value;
            target[index++] = (byte)(value >> 8);
            target[index++] = (byte)(value >> 16);
            target[index] = (byte)(value >> 24);
        }
    }
    

提交回复
热议问题