c# – 奇怪的表现行为

栏目: ASP.NET · 发布时间: 6年前

内容简介:代码日志版权声明:翻译自:http://stackoverflow.com/questions/32071087/weird-performance-behavior

所以我有这2个方法,假设将1000个长整数的整数乘以2.

第一种方法:

[MethodImpl(MethodImplOptions.NoOptimization)]
Power(int[] arr)
{
    for (int i = 0; i < arr.Length; i++)
    {
        arr[i] = arr[i] + arr[i];
    }
}

第二种方法:

[MethodImpl(MethodImplOptions.NoOptimization)]
PowerNoLoop(int[] arr)
{
    int i = 0;
    arr[i] = arr[i] + arr[i];
    i++;
    arr[i] = arr[i] + arr[i];
    i++;
    arr[i] = arr[i] + arr[i];
    i++;
    ............1000 Times........
    arr[i] = arr[i] + arr[i];
}

请注意,我将此代码仅用于性能研究,这就是为什么它看起来很恶心.

令人吃惊的结果是,Power已经比PowerNoLoop快了近50%,即使我检查了它们的反编译的IL源,并且For循环的内容与PowerNoLoop中的每一行完全相同.

怎么会这样?

从我的机器的一个样品测量,运行测试10次,PowerNoLoop是第一:

00:00:00.0277138 00:00:00.0001553
00:00:00.0000142 00:00:00.0000057
00:00:00.0000106 00:00:00.0000053
00:00:00.0000084 00:00:00.0000053
00:00:00.0000080 00:00:00.0000053
00:00:00.0000075 00:00:00.0000053
00:00:00.0000080 00:00:00.0000057
00:00:00.0000080 00:00:00.0000053
00:00:00.0000080 00:00:00.0000053
00:00:00.0000075 00:00:00.0000053

是的,慢50%左右值得注意的是,首次通过测试时的抖动开销,显然它会燃烧更多的核心,试图得到这个巨大的方法编译.请记住,当您不禁用优化器时,测量值会大不相同,所以无循环版本的速度会慢一些〜800%.

首先总是寻找一个解释是生成的机器代码,你可以看到它与Debug> Windows>拆卸.主要的麻烦是PowerNoLoop()方法的序幕.在x86代码中看起来像这样:

067E0048  push        ebp                       ; setup stack frame
067E0049  mov         ebp,esp  
067E004B  push        edi                       ; preserve registers
067E004C  push        esi  
067E004D  sub         esp,0FA8h                 ; stack frame size = 4008 bytes  
067E0053  mov         esi,ecx  
067E0055  lea         edi,[ebp-0ACCh]           ; temp2 variables
067E005B  mov         ecx,2B1h                  ; initialize 2756 bytes
067E0060  xor         eax,eax                   ; set them to 0
067E0062  rep stos    dword ptr es:[edi]

注意非常大的堆栈大小,4008字节.对于只有一个局部变量的方法来说太多了,它只需要8个字节.额外的4000个是临时变量,我把它命名为temp2.它们由代码指令初始化为0,这需要一段时间.我不能解释2756.

个人补充是非优化代码中非常漂亮的事情.我将为您提供机器代码转储,并将其写入等效的C#代码:

if (i >= arr.Length) goto throwOutOfBoundsException
var temp1 = arr[i];
if (i >= arr.Length) goto throwOutOfBoundsException
var temp2 = temp1 + arr[i];
if (i >= arr.Length) goto throwOutOfBoundsException
arr[i] = temp2

一遍又一遍地重复,总共一千次. temp2变量是麻烦制造者,每个单独的语句有一个.因此,为堆栈帧大小添加4000字节.如果有人猜到2756,那么我很乐意在评论中听到.

在方法开始运行之前,必须将它们全部设置为0,大概是什么导致50%的减速.也可能有一些指令提取和解码开销,它不能从测量中轻松隔离.

值得注意的是,当您删除[MethodImpl]属性并允许优化器执行其作业时,它们不会被消除.实际上,该方法根本没有优化,因为它不想解决这么大的代码块.

总结你应该画的是永远保持抖动优化器为你展开循环.它知道得更好

代码日志版权声明:

翻译自:http://stackoverflow.com/questions/32071087/weird-performance-behavior


以上所述就是小编给大家介绍的《c# – 奇怪的表现行为》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

JavaScript DOM编程艺术 (第2版)

JavaScript DOM编程艺术 (第2版)

[英] Jeremy Keith、[加] Jeffrey Sambells / 杨涛、王建桥、杨晓云 等 / 人民邮电出版社 / 2011-4 / 49.00元

JavaScript是Web开发中最重要的一门语言,它强大而优美。无论是桌面开发,还是移动应用。JavaScript都是必须掌握的技术。W3C的DOM标准是开发Web应用的基石。已经得到所有现代浏览器的支持,这使得跨平台Web开发成了一件轻松惬意的事。 本书是超级畅销书的升级版,由倡导Web标准的领军人物执笔,揭示了前端开发的真谛,是学习JavaScript和DOM开发的必读之作。 本......一起来看看 《JavaScript DOM编程艺术 (第2版)》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器