c# – 奇怪的表现行为

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

内容简介:代码日志版权声明:翻译自: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# – 奇怪的表现行为》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

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

数据结构与算法:python语言实现

数据结构与算法:python语言实现

迈克尔.·T·古德里奇、罗伯托·塔玛西亚、迈克尔·H·戈德瓦瑟 / 张晓、赵晓南 / 机械工业出版社 / 2018-9 / 109.00元

本书采用Python语言讨论数据结构和算法,详细讲解其设计、分析与实现过程,是一本内容全面且特色鲜明的教材。书中将面向对象视角贯穿始终,充分利用Python语言优美而简洁的特点,强调代码的健壮性和可重用性,关注各种抽象数据类型以及不同算法实现策略的权衡。一起来看看 《数据结构与算法:python语言实现》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具