C#性能优化实践2013-11-13 infoq 胡森性能主要指两个方面:内存消耗和执行速度。性能优化简而言之,就是在不影响系统运行正确性的前提下 ,使之运行地更快,完成特定功能所需的时间更短。本文以.NET平台下的控件产品MultiRow为例,描 述C#性能优化的实践。性能优化原则理解需求MultiRow的一个性能需求是:“百万行 数据绑定下平滑滚动。”整个MultiRow项目的开发过程一直在考虑这个目标。· 理解瓶颈99%的性能消耗是由于1%的代码造成的。大部分性能优化都是针对这1%的瓶颈代码进行的。具体实施也 就分为两步:“发现瓶颈”和“消除瓶颈”。· 切忌过度性能优化本身是有成本的。这个成 本不单单体现在做性能优化所付出的工作量,还包括为性能优化而写出复杂的代码导致额外的维护成本,比如 引入新的Bug,额外的内存开销等。性能优化常常需要在收益和成本之间做出权衡。如何发现性能瓶颈性能优化的第一步是发现性能瓶颈,下面是一些定位性能瓶颈的实践。· 如何获取内存消耗以下代码可以获取某个操作的内存消耗。
long start = GC.GetTotalMemory(true);// 在这里写需要被测试内存消耗的代码,例如,创建一个GcMultiRowvar gcMulitRow1 = new GcMultiRow();GC.Collect();// 确保所有内存都被GC回收GC.WaitForFullGCComplete();long end = GC.GetTotalMemory(true);long useMemory = end - start;
如何获取时间消耗以下代码可以获取某个操作时间消耗。
System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();watch.Start();for (int i = 0; i < 1000; i++){gcMultiRow1.Sort();}watch.Stop();var useTime = (double)watch.ElapsedMilliseconds / 1000;
为了获得更加稳定的时间消耗,这里 把一个操作循环执行了1000次,取时间消耗的平均值以排除不稳定数据。· ANTS Performance ProfilerANTS Performance Profiler是款功能强大的性能检测软件。熟练使用这个工具,我们可以 快速准确的定位到有性能问题的代码。这是一款收费软件,会在IL中加入一些钩子用来记录时间,所以在分析 时,软件的执行速度会比实际运行慢一些,获得的数据也因此并不是百分之百的准确,还要结合其他技巧来分 析程序的性能。· CodeReviewCodeReview是发现性能问题的最后手段。CodeReview应该对产 品的性能瓶颈尽可能多的关注,确保该部分逻辑执行的尽可能的快。性能优化的方法和技巧定 位了性能问题后,解决的办法有很多。下面是一些性能优化的技巧和实践。· 优化程序结构在设计时就应该考虑产品结构是否可以达到性能需求。如果后期发现了性能问题,调整结构会带来非常大的开 销。例如:GcMultiRow要支持100万行数据。假设每行有10列的话,就需要有1000万个单元格 ,每个单元格上又有很多的属性。如果不做任何优化,大数据量时,一个GcMultiRow软件的内存开销会相当的 大。GcMultiRow采用的方案是使用哈希表来存储行数据:只有用户改过的行放到哈希表里,大部分没有改过的 行都直接使用模板代替。这就达到了节省内存的目的。WPF平台和Silverlight平台的画法和Winform平 台不同,是通过组合Visual元素的方法实现的。SpreadGrid for WPF产品同样支持百万级的数据量,但是又不 能给每个单元格都分配一个View。所以SpreadGrid使用了VirtualizingPanel来实现画法。思路是每一个 Visual是一个Cell的展示模块,可以和Cell的数据模块分离,这样就只需要为显示出来的Cell创建Visual。当 发生滚动时会有一部分Cell滚出屏幕,有一部分Cell滚入屏幕。这时,让滚出屏幕的Cell和Visual分离,然后 再复用这部分Visual给新进入屏幕的Cell。如此循环,就只需要几百个Visual就可以支持很多的Cell。