用工具提升程序的性能和稳定性

这里说的性能指的主要是运行速度,而稳定性则侧重内存泄漏方面。这篇文主要讲述利用VSTS的Performance Profiler寻找性能瓶颈并做出优化的大体思路,以及利用Power Toys for .NET CF寻找.NET mobile程序的内存泄漏点的基本方法。

性能

一个程序性能不佳,亦即对于一定量的输入数据,得到结果耗时过长,原因不外乎拙劣的算法或蹩脚的实现。算法方面相对好查一些,毕竟时间复杂度大体估计下还是差不多的。对于实现方面的问题,空想式的理论分析显然不管用,而代码排查对于稍微大一点的程序就不切实际,更何况有时候误用了低效的函数自己都不知道,把代码看再多遍也没用。从另一个角度来看,一个上规模的程序性能之所以不好,一般都存在一个或数个瓶颈。换言之,它可能90%的时间都在某两个函数里面转,这样就算把剩下的10%优化的再好,程序的性能也上不去。因此,我们需要一个工具来告诉我们,程序的大部分时间都在哪个函数里,有的放矢方有可能百发百中。
所幸VSTS (Visual Studio Team System) 提供了一个相关工具:Performance Profiler。具体的用法MSDN上面都有,而针对WPF代码VS2010又有更多更强大的特性,可以自行学习。只是VS08似乎没有提供对每一行代码Inclusive Time的统计功能,而这个数据又十分重要。要想得到的话,目前我所知的方法就是只有把该行代码注掉运行一下,看和正常运行时间有多少差值了…囧 (不过VS2010似乎提供了这个功能)
知道一个程序的性能瓶颈后,接下来就是有针对性的优化。由于阅历所限,我个人目前遇到的性能问题主要由两个因素引起:一个是不必要的冗余执行,一个是误用了低效率的函数/类。前一个比较好理解,比如前面做了一坨计算,把结果存在数组A里面,可是不久之后在A的内容没有改动的情况下又做了同样的一坨运算。这就造成了计算资源的浪费。对于这一类问题,似乎没有什么特效的解决方法,只能根据瓶颈所在排查代码了。后一种问题则主要是一些类使用上的讲究没有搞清楚,比如GDI+中SetPixel()和GetPixel()是很低效的,要用LockBits()来直接内存读写比较高效,又如CombinedGeometryUnion操作比GeometryGroup慢200多倍等等。对于这一类问题,在发现某个函数莫名占用过多时间时,查查MSDN,注意看其中关于效率的描述,多半很快就能解决。这里有以前的一个实例,可以参考一下。

稳定性

虽然.Net Framework提供了自动垃圾回收等防止内存泄漏的功能,我们不需要像C++那样很小心,但内存泄漏的问题仍然是存在的。究其原因,是很多资源不是.NET能自动释放的,比如GDI的句柄,GDI+ Image的句柄(本质还是封装了GDI)等等。这些资源如果不及时手动回收,很容易引起系统问题。比如开发手机程序的时候经常碰到OutOfMemoryException满天飞,甚至系统菜单都不能正常显示的情况。
在急于寻求相应的解决方法之前,我们必须要了解C#对于这些资源还是提供了自动化的解决方法的,那就是IDisposable接口。我们在实现一个调用了系统资源的类时,一方面尽可能应当利用usingtry/finally自动释放使用完毕的资源,一方面也要给这个类实现IDisposable接口,在编码时就用良好的习惯堵住内存泄漏的源头,这才是王道。
在了解了C#对非托管资源的处理方式之后,为了维持程序的稳定性,我们就需要了解两个信息:当前程序有没有内存泄漏?在何处出现了内存泄漏?对于手机上的开发,这一点尤其重要。再次庆幸微软提供了手机端的.NET内存调试工具:Power Toys for .NET Compact Framework. 大概的用法见这里
有了Power Toys之后,就能够很轻松的看出是哪种内存泄漏,比如如果出现了下图中的情况,就黄容易知道是Bitmap在创建之后没有及时Dispose掉。同时由于每秒的Delta值恒定为2,可以推断出和某个Interval >= 500ms的Timer有关。有了这些线索,就很容易排查出来问题所在了。由于这些数据是实时统计的,对于一些不是始终出现的泄漏问题也可以根据出现的时机判断大概的代码段。

PowerToys图1 用.NET CF Remote Performance Monitor判断内存泄漏

总的来说,这篇文介绍了两个工具,对Windows下桌面程序性能的提高和移动程序内存泄漏的检测提出了一些思路。可喜的是这些工作都有相配套的工具,可惜的是自动化程度仍略嫌不够,需要编码人员有较强的素养才能迅速解决问题。

对于BBS DotNet版上出现的C#没有技术含量的论调,这篇文似乎也能说明:虽然C#入门门槛低,但想真正写出一手好程序也不简单,此中高手同样能在公司到达“不可取代”的境界。

posted on 2010-01-25 22:39  grapeot  阅读(466)  评论(0编辑  收藏  举报

导航