享受release版本发布的好处的同时也应该警惕release可能给你引入
一般我们发布项目的时候通常都会采用release版本,因为release会在jit层面对我们的il代码进行了优化,比如在迭代和内存操作的性能提升方面,废话不多说, 我先用一个简单的“冒泡排序”体验下release和debug下面的性能差距。
这个是我多年前写的算法系列中的一个冒泡排序的例子,就随手翻出来展示一下,准备灌入50000条数据,这样就可以执行25亿次迭代,王健林说,不能太张 狂,几十亿对我来说不算小意思,算中等意思吧。 Main( rand = List<> list = List<>
( i = ; i < ; i++
watch =
Console.WriteLine(
List<> BubbleSort(List<>
( i = ; i < list.Count - ; i++ i: 从后往前的的下标一定大于从前往后的下标,否则就超越了。
( j = list.Count - ; j > i; j--
(list[j - ] > temp = list[j - list[j - ] = list[j] = }
从上面两张图可以看到,debug和release版本之间的性能差异能达到将近4倍的差距。。。还是相当震撼的。
release确实是一个非常好的东西,但是在享受好处的同时也不要忘了,任何优化都是要付出代价的,这世界不会什么好事都让你给占了,release有时候为了 性能提升,会大胆的给你做一些代码优化和cpu指令的优化,比如说把你的一些变量和参数缓存在cpu的高速缓存中,不然的话,你的性能能提升这么多么~~~ 绝大多数情况下都不会遇到问题,但有时你很不幸,要出就出大问题,下面我同样举一个例子给大家演示一下: Main( isStop =
task = Task.Factory.StartNew(() =>
isSuccess =
(! isSuccess = !
Thread.Sleep( isStop =
Console.WriteLine( }
上面这串代码的意思很简单,我就不费劲给大家解释了,但是有意思的事情就是,
不信的话你可以看看下面的截图嘛。。。
刚才也说过了,release版本会在jit层面对il代码进行优化,所以看应用程序的il代码是看不出什么名堂的,但是可以大概能猜到的就是,要么jit直接把代码 (! isSuccess = ! }
优化成了 ( isSuccess = ! }
要么就是为了加快执行速度,mainthread和task会将isStop变量从memory中加载到各自的cpu缓存中,而主线程执行isStop=true的时候而task读的还是cpu 缓存中的
那这个问题该怎么解决呢?大家第一个想到的就是volatile关键词,这个关键词我想大家都知道有2个意思: . 告诉编译器,jit,cpu不要对我进行任何形式的优化,谢谢。 . 该变量必须从memory中读取,而不是cpu cache中。 所以可以将上面的代码优化成如下方式,问题就可以完美解决: isStop =
Main( task = Task.Factory.StartNew(() =>
isSuccess =
(! isSuccess = !
Thread.Sleep( isStop =
Console.WriteLine( }
这个方法也是.net后来新增的一个方法,它的作用就是告诉CLR,我需要从memory中进行读取,而不是cpu cache中,不信可以看下注释。
VolatileRead( address);
不过很遗憾,这吊毛没有bool类型的参数,只有int类型。。。操,,,为了测试只能将isStop改成0,1这两种int状态,哎。。。 Main( isStop =
task = Task.Factory.StartNew(() =>
isSuccess =
(isStop !=
Thread.VolatileRead(
isSuccess = !
Thread.Sleep( isStop =
Console.WriteLine( }
其实这个方法在MSDN上的解释看起来让人觉得莫名奇妙,根本就看不懂。
MemoryBarrier();
其实这句话大概就两个意思: . 优化cpu指令排序。 . 调用MemoryBarrier之后,在MemoryBarrier之前的变量写入都要从cache更新到memory中。
所以基于上面两条策略,我们可以用Thread.MemoryBarrier进行改造,代码如下: Main( isStop =
task = Task.Factory.StartNew(() =>
isSuccess =
(! isSuccess = !
Thread.Sleep( isStop =
Console.WriteLine( }
总结一下,,原因我想大家都明白了,这个时候你就可以用到上面三种手段进行解决 啦。。。好了,本篇就说到这里,希望对你有帮助。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |