zyl910

优化技巧、硬件体系、图像处理、图形学、游戏编程、国际化与文本信息处理。

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  192 随笔 :: 0 文章 :: 115 评论 :: 0 引用

公告

前面的三次测试都是在同一个项目内的,既处于同一个程序集。那么,跨程序集调用会怎么样呢?

因为为了保证可维护性,我们会把一些常用操作封装到类库中去。然后实际项目开发时,引用该类库,使得解决方案中存在多个项目。编译完成后,将会是一个主要的exe和若干个dll文件,主exe程序集中的代码会调用dll程序集,既形成了跨程序集调用。

分析跨程序集调用的性能,有助优化类库架构的设计。


一、测试办法

其实步骤很简单——
1.重新打开VS2005。或关闭解决方案。
2.新建一个“Windows应用程序”项目。如“TryPointerCallns2005”。
3.添加项目,选择上次的“TryPointerCall2005”。现在解决方案中就有两个项目了。
4.选择第2步时新建的项目(TryPointerCallns2005),添加引用,将“TryPointerCall2005”加上去。
5.调整项目属性,允许不安全的代码。
6.新建一个类(TestCall),将测试代码全部Copy过来(注意只复制测试代码,不复制IPointerCall、PointerCall等实现)。
7.修改窗口界面,调用TestCall的测试代码。


二、测试环境

  编译器——
VS2005:Visual Studio 2005 SP1。
采用上述编译器编译为Release版程序,最大速度优化。

  机器——
HP CQ42-153TX
处理器:Intel Core i5-430M(2.26GHz, Turbo 2.53GHz, 3MB L3)
内存容量:2GB (DDR3-1066)


三、测试结果

  测试结果如下——
== PointerCallTool.TryIt() ==
硬编码.栈变量: 162
硬编码.栈分配: 168
硬编码.静态: 164
静态调用: 160
64硬编码.栈变量: 161
64硬编码.栈分配: 160
64硬编码.静态: 160
64静态调用: 162
调用派生类: 1118
调用密封类: 1049
调用结构体: 1069
调用基类: 1128
调用派生类的接口: 1132
调用密封类的接口: 1135
调用结构体的接口: 1453
基类泛型调用派生类: 1769
基类泛型调用基类: 1774
接口泛型调用派生类: 2230
接口泛型调用密封类: 2240
接口泛型调用结构体: 1215
接口泛型调用结构体引用: 1127
接口泛型调用基类: 2241
接口泛型调用派生类的接口: 2230
接口泛型调用密封类的接口: 2244
接口泛型调用结构体的接口: 2302


  可见,在跨程序集调用时,调用密封类、调用结构体不会被即时编译器(JIT)做内联优化,而被当做普通的虚方法调用。

  所以,对于那些要求性能的代码,应尽量保证在同一程序集内,避免将其放在类库工程,这样能尽可能地利用即时编译器(JIT)内联优化的机会。

(完)

源代码下载——
http://files.cnblogs.com/zyl910/TryPointerCall_4.rar


目录——
C#类与结构体究竟谁快——各种函数调用模式速度评测:http://www.cnblogs.com/zyl910/archive/2011/09/19/2186623.html
再探C#类与结构体究竟谁快——考虑栈变量、栈分配、64位整数、密封类:http://www.cnblogs.com/zyl910/archive/2011/09/20/2186622.html
三探C#类与结构体究竟谁快——MSIL(微软中间语言)解读:http://www.cnblogs.com/zyl910/archive/2011/09/24/2189403.html
四探C#类与结构体究竟谁快——跨程序集(assembly)调用:http://www.cnblogs.com/zyl910/archive/2011/10/01/2197844.html

posted on 2011-10-01 23:13 zyl910 阅读(...) 评论(...) 编辑 收藏