繁体   English   中英

C#结构分配效率

[英]C# struct assignment efficiency

在C#中,我有一个结构数组,我需要为每个结构赋值。 最有效的方法是什么? 我可以分配每个字段,为每个字段索引数组:

array[i].x = 1;
array[i].y = 1;

我可以在堆栈上构造一个新的结构并将其复制到数组中:

array[i] = new Vector2(1, 2);

还有另外一种方法吗? 我可以调用一个方法并通过ref传递结构,但我猜测方法调用开销不值得。

如果结构大小很重要,那么所讨论的结构有2-4个float或byte类型的字段。

在某些情况下,我需要为多个数组条目分配相同的值,例如:

Vector2 value = new Vector2(1, 2);
array[i] = value;
array[i + 1] = value;
array[i + 2] = value;
array[i + 3] = value;

这会改变哪种方法更有效吗?

我知道这是相当低的水平,但我做了数百万次,我很好奇。

编辑:我打了一个基准:

this.array = new Vector2[100];
Vector2[] array = this.array;
for (int i = 0; i < 1000; i++){
    long startTime, endTime;
    startTime = DateTime.Now.Ticks;
    for (int x = 0; x < 100000000; x++) {
        array[0] = new Vector2(1,2);
        array[1] = new Vector2(3,4);
        array[2] = new Vector2(5,6);
        array[3] = new Vector2(7,8);
        array[4] = new Vector2(9,0);
        array[5] = new Vector2(1,2);
        array[6] = new Vector2(3,4);
        array[7] = new Vector2(5,6);
        array[8] = new Vector2(7,8);
        array[9] = new Vector2(9,0);
    }
    endTime = DateTime.Now.Ticks;
    double ns = ((double)(endTime - startTime)) / ((double)loopCount);
    Debug.Log(ns.ToString("F"));
}

这报告了〜0.77ns,另一个索引并分配了结构域的版本给出了~0.24ns,FWIW。 与结构堆栈分配和复制相比,数组索引看起来很便宜。 在移动设备上看到性能可能会很有趣。

编辑2:丹·布莱恩特下面的回答是为什么我没有写一个基准开始,太容易出错。

我很好奇第一种情况(字段赋值与构造函数调用),所以我做了一个发布版本并附加了post-JIT以查看反汇编。 (x64)代码如下所示:

            var array = new Vector2[10];
00000000  mov         ecx,191372h 
00000005  mov         edx,0Ah 
0000000a  call        FFF421C4 
0000000f  mov         edx,eax 

            array[i].x = 1;
00000011  cmp         dword ptr [edx+4],0 
00000015  jbe         0000003E 
00000017  lea         eax,[edx+8] 
0000001a  fld1 
0000001c  fstp        qword ptr [eax] 
            array[i].y = 1;
0000001e  fld1 
00000020  fstp        qword ptr [edx+10h] 

            array[i] = new Vector2(1, 1);
00000023  add         edx,8 
00000026  mov         eax,edx 
00000028  fld1 
0000002a  fld1 
0000002c  fxch        st(1) 
0000002e  fstp        qword ptr [eax] 
00000030  fstp        qword ptr [eax+8] 

值得注意的是,在调试器外部使用发布版本时会内联“构造函数调用”,因此,原则上,设置字段或调用构造函数之间应该没有区别。 也就是说,抖动在这里做了一些有趣的事情。

对于'构造函数'版本,它使用两个浮点堆栈槽并将它们同时存储到结构存储器(fld1,fld1,fstp,fstp。)它还有一个fxch(交换),这有点傻对于大多数应用程序,两个插槽都包含常量值1,但不是完全高优先级的优化目标,我假设。

对于“单个字段”版本,它只使用FPU堆栈上的一个插槽,通过拆分写入(fld1,fstp,fld1,fstp)。 我不是x64大师,所以我不知道哪个排序在执行时间方面更有效率。 但是,任何差异可能都是微不足道的,因为主要的潜在开销(构造函数方法调用)是内联的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM