我可以使用相同的字节到其他类型的值/对象

本文关键字:其他 类型 对象 字节 可以使 我可以 | 更新日期: 2023-09-27 18:15:53

因为我的目标是超越 List<T> 我正在测试数组,发现很少有开始测试的起点在尝试从屏幕上捕获位图之前,我已经测试了这个,经试验证明,使用效果良好。我的问题是什么数据类型可以使用这个Copy()代码,除了byte[]

说我想要一个数据存储单元利用非托管/不安全的优势

        public unsafe struct NusT
        {
            public unsafe int vi;
            public unsafe bool vb;
        }

而不是填充列表

i按如下方式初始化结构体:

NusT n; 
n.vi= 90;
n.vb=true

我在测试了以下内容之后测试了这个:

NusT n = new NusT(){vi=90, vb=true};
3)

NusT n = new NusT("90", true);

我认为最后两个都有相同的结果,但第一个非常快,因为我没有创建对象,所以

NusT n-> instructions- 1
n.vi=90 -> instructions- 1
n.vb=true -> instructions- 1 

现在我最小化了我能做到的,这是从一个类开始的:这比2 & &;因为它也使用属性

class bigAndSlow
{
     public int a { get; private set;}
     public bool b { get; private set;}
     public string  c { get; private set;}
     public bigAndSlow(int .. ,boo .. , string.. )
     {
        initialise ...
     }
}

所以现在当最终决定是

        public unsafe struct NusT
        {
            public unsafe int vi;
            public unsafe bool vb;
        }

我如何实现这个极快的数据单元在

上使用Copy()
NusT[] NustyArr;

    static unsafe void Copy(byte[] src, int srcIndex,
            byte[] dst, int dstIndex, int count)
        {
            if (src == null || srcIndex < 0 ||
                dst == null || dstIndex < 0 || count < 0)
            {
                throw new ArgumentException();
            }
            int srcLen = src.Length;
            int dstLen = dst.Length;
            if (srcLen - srcIndex < count ||
                dstLen - dstIndex < count)
            {
                throw new ArgumentException();
            }

            // The following fixed statement pins the location of
            // the src and dst objects in memory so that they will
            // not be moved by garbage collection.          
            fixed (byte* pSrc = src, pDst = dst)
            {
                byte* ps = pSrc;
                byte* pd = pDst;
                // Loop over the count in blocks of 4 bytes, copying an
                // integer (4 bytes) at a time:
                for (int n = 0; n < count / 4; n++)
                {
                    *((int*)pd) = *((int*)ps);
                    pd += 4;
                    ps += 4;
                }
                // Complete the copy by moving any bytes that weren't
                // moved in blocks of 4:
                for (int n = 0; n < count % 4; n++)
                {
                    *pd = *ps;
                    pd++;
                    ps++;
                }
            }
        }

        static void Main(string[] args)
        {
            byte[] a = new byte[100];
            byte[] b = new byte[100];
            for (int i = 0; i < 100; ++i)
                a[i] = (byte)i;
            Copy(a, 0, b, 0, 100);
            Console.WriteLine("The first 10 elements are:");
            for (int i = 0; i < 10; ++i)
                Console.Write(b[i] + " ");
            Console.WriteLine("'n");
        }

我可以使用相同的字节到其他类型的值/对象

是的,您可以对任何blittable类型执行此操作。位元类型是基本类型(整型和浮点型,但不是bool型)、位元类型的一维数组和只包含位元类型字段的结构体。

结构体NusT由于包含bool域而不可位比特化。只需将其更改为byte,您将获得一个可以获得指针的blittable结构。

下面是适用于任何类型的代码:
static unsafe void UnsafeCopy<T>(T[] src, int srcIndex, T[] dst, int dstIndex, int count) where T : struct
{
    if (src == null || srcIndex < 0 || dst == null || dstIndex < 0 || count < 0 || srcIndex + count > src.Length || dstIndex + count > dst.Length)
    {
        throw new ArgumentException();
    }
    int elem_size = Marshal.SizeOf(typeof(T));
    GCHandle gch1 = GCHandle.Alloc(src, GCHandleType.Pinned);
    GCHandle gch2 = GCHandle.Alloc(dst, GCHandleType.Pinned);
    byte* ps = (byte*)gch1.AddrOfPinnedObject().ToPointer() + srcIndex * elem_size;
    byte* pd = (byte*)gch2.AddrOfPinnedObject().ToPointer() + dstIndex * elem_size;
    int len = count * elem_size;
    try
    {
        // Loop over the count in blocks of 4 bytes, copying an
        // integer (4 bytes) at a time:
        for (int n = 0; n < len / 4; n++)
        {
            *((int*)pd) = *((int*)ps);
            pd += 4;
            ps += 4;
        }
        // Complete the copy by moving any bytes that weren't
        // moved in blocks of 4:
        for (int n = 0; n < len % 4; n++)
        {
            *pd = *ps;
            pd++;
            ps++;
        }
    }
    finally
    {
        gch1.Free();
        gch2.Free();
    }
}

但是我强烈建议你使用Array.Copy。这已经是复制数组最有效的方式了。请参阅下面的1M元素数组复制的基准测试:

byte[]数组。拷贝:57,491 us

byte[] FastCopy: 138,198 us

byte[] JustCopy: 792,399 us

byte[] UnsafeCopy: 138,575 us

byte[] MemCpy: 57,667 us

雄厚[]数组。拷贝:1197 ms

NusT[] JustCopy: 1843 ms

NusT[] UnsafeCopy: 1,550 ms

NusT[] MemCpy: 1,208 ms

FastCopy是你的复制函数,UnsafeCopy是我的模板函数,JustCopyfor (int i = 0; i < src.Length; i++) dst[i] = src[i];的简单实现。MemCpy是msvcrt memcpy函数的PInvoke调用。

结论是:在c#中使用指针来提高性能是一个不好的做法。JIT不会优化不安全的代码。最好的解决方案是将性能关键代码移到本机dll中。