这次试验的结果是,在.NET CF 3.5+Windows Mobile 5模拟器的环境下,该程序中循环的速度为425次每秒,这比刚才的本地代码要慢15%,而在同样的Dell Axim设备上,该程序只有210次每秒的表现。比之前的本地代码要慢上19%。
桌面PC机上的测试
通常来说,托管代码和本地代码的效率应该5%左右,充其量有10%的差别,而以上结果(15%~20%)确实有些让人感到意外。考虑到有可能是.NET Compact Framework和我们通常用的桌面版本的Framework有所不同,接下来我们再来做一个桌面PC机上的测试。我们稍稍改动了一下代码,加了几条预编译指令,让之前的代码托管代码能在PC机上运行。结果是托管的程序循环速度为825次每秒,本地代码的程序循环速度则达到了6200次每秒。这比托管的程序快了625%!!
改进后的托管代码
为什么托管代码会如此之慢,设想那些托管方法如Graphics.FillRectangle只是通过P/invoke对Win32API FillRect的简单封装。那何不直接P/invoke来调用本地GDI代码呢,这样可以减少方法调用的次数。
改进后测试结果表明性能有所提高,在模拟器和Axim上分别达到了455和225次每秒,较之前提高了7%。这将托管代码和本地代码的差别缩小了一半。再回到桌面上,测试结果让人更加吃惊,托管代码也达到了每秒6150次循环。和之前的本地代码只差了1%。看来,托管代码并不总是比本地代码慢那么多。
总结
经过在不同设备,不同平台上的试验,证明了托管代码至少在基本的GDI操作方面确实比非托管代码要慢,但并不总是慢那么多。下表列举了一些实验数据:
测试结果是,在Windows Mobile 5.0的模拟器上,执行循环的速度为490次每秒(当然这跟你PC机的性能是有关的)。每一次操作包括了填充矩形和绘制两个椭圆的过程。在一台Windows Mobile 5.0 Dell Axim x51(PXA270处理器)的实际设备上,这个程序可以达到250次每秒的循环速度。
Compact Framework下的测试
厄,实际上这是一份和上面的代码很类似的C#代码: