对《基于动态代码生成技术的动态对象工厂》一文的补充
2007-02-24 02:00
399 查看
写完《基于动态代码生成技术的动态对象工厂》一文后我一直很奇怪为什么动态代码生成的方法相对于直接使用new有如此大的劣势?道理上说动态代码一旦生成,那么它和原生代码应该也没什么区别了,那么它的执行效率应该和相应的原生代码差别不大才对。仔细观察Creator.New版本的执行过程,我猜测问题并不是出在动态生成的代码本身,而是出在周围的代码上。在我的测试程序中,我对以下代码返复调用1000万次:
A a = (A)Creator.New(typeof(A), "a");
而Createor.New方法中要对一个SortedList进行查找,找到满足条件的Creator子类实例,然后调用它的CreateObject方法来产生对象,此查找的过程可能会很影响效率,为此我把测试部分的代码改为如下:
object[] param = new object[] ...{ "a" };
Creator creator = Creator.GetCreator(typeof(A), param);
DateTime dt3 = DateTime.Now;
for (int i = 0; i < count; i++)
...{
A a = (A)creator.CreateObject(param);
}
DateTime dt4 = DateTime.Now;
显然这样做给了动态代码生成方式很大的优待,我首先取得了合适的creator子类对象,并且已经把要传的参数数组准备好了,循环里面所做的只是单纯调用动态生成的代码。不过这没关系,我就是要看看在极优环境下动态生成的代码的执行效率如何,相比直接使用new会差多少。相应的,对直接使用new方法的测试代码如下:
DateTime dt4 = DateTime.Now;
for (int i = 0; i < count; i++)
...{
A a = new A("a");
}
DateTime dt5 = DateTime.Now
为了减少影响,这里的循环上限count都被声明为const,在编译的结果中会以其值直接替代。这里为了减少误差,把循环次数增加到一亿次。此外我还把所有的构造函数的方法体都改成空的,以减少这些操作需要的时间。这样测得的结果如下:
[align=center]优化后重复一亿次所需时间(毫秒)[/align]
下面是关于此结果的几点分析:
1 此次测试结果明显好于上一次,动态生成的代码运行时间只是直接使用new的2-4倍。可见前面所做的分析是正确的,执行动态代码本身和执行原生代码在效率上没有什么差别。
2 之所以仍有2-4倍的差别,我觉得是因为动态生成的代码在参数进栈时需要先从数组中取得参数才能进栈,这样显然比直接使用new时用ldstr或类似指令要慢一些,2-4倍的差别比较正常
3 参数为引用类型动态代码的时间只是new的2倍多,而参数为值类型时倍数则较多,这是因为参数为引用类型时在从数组中取值之后需要一个拆箱操作,显然此操作是非常慢的。
4 调用动态代码时参数个数不同时所需时间也会增加,这个和预想的一样,因为由动态生成代码的部分可以看出,参数越多for循环执行的次数也越多,生成的IL代码就越长。
5 代码执行时间并不随参数的个数成倍数关系增长,这里大概因为从数组中取值的速度比较快,而newobj指令是最慢的,因此参数个数的影响不是很大。但参数为值类型时,时间增长的较快,这更说明了拆箱操作是很慢的,对结果的影响较大
6 参数为一个值类型时比参数为一个引用类型时动态代码所用的时间更短(值类型时为1937.5),引用类型时为(2312.5),但直观想象的话应该是引用类型的快一些才对,因为它不需要拆箱,并且拆箱也是个慢操作,但这与测试结果不符,我还不太清楚这是为什么。
7因同一段代码返复测试时时间也会有一些浮动,因此可以认为各种不同参数时new方法的时间几乎没有差别,可见像ldstr、ldc.i4这样的压栈操作速度是非常快的,相对于newobj来说几乎可以忽略不计。
A a = (A)Creator.New(typeof(A), "a");
而Createor.New方法中要对一个SortedList进行查找,找到满足条件的Creator子类实例,然后调用它的CreateObject方法来产生对象,此查找的过程可能会很影响效率,为此我把测试部分的代码改为如下:
object[] param = new object[] ...{ "a" };
Creator creator = Creator.GetCreator(typeof(A), param);
DateTime dt3 = DateTime.Now;
for (int i = 0; i < count; i++)
...{
A a = (A)creator.CreateObject(param);
}
DateTime dt4 = DateTime.Now;
显然这样做给了动态代码生成方式很大的优待,我首先取得了合适的creator子类对象,并且已经把要传的参数数组准备好了,循环里面所做的只是单纯调用动态生成的代码。不过这没关系,我就是要看看在极优环境下动态生成的代码的执行效率如何,相比直接使用new会差多少。相应的,对直接使用new方法的测试代码如下:
DateTime dt4 = DateTime.Now;
for (int i = 0; i < count; i++)
...{
A a = new A("a");
}
DateTime dt5 = DateTime.Now
为了减少影响,这里的循环上限count都被声明为const,在编译的结果中会以其值直接替代。这里为了减少误差,把循环次数增加到一亿次。此外我还把所有的构造函数的方法体都改成空的,以减少这些操作需要的时间。这样测得的结果如下:
[align=center]优化后重复一亿次所需时间(毫秒)[/align]
[align=center]调用方式[/align] | [align=center]Creator.CreateObject[/align] | [align=center]直接使用new[/align] | |
[align=center]引用类型参数[/align] | 1个参数 | 2312.5 | 1093.75 |
3个参数 | 2593.75 | 1109.375 | |
9个参数 | 2687.5 | 1093.75 | |
[align=center]值类型参数[/align] | 1个参数 | 1937.5 | 1078.125 |
3个参数 | 3000 | 1093.75 | |
9个参数 | 5343.75 | 1093.75 |
1 此次测试结果明显好于上一次,动态生成的代码运行时间只是直接使用new的2-4倍。可见前面所做的分析是正确的,执行动态代码本身和执行原生代码在效率上没有什么差别。
2 之所以仍有2-4倍的差别,我觉得是因为动态生成的代码在参数进栈时需要先从数组中取得参数才能进栈,这样显然比直接使用new时用ldstr或类似指令要慢一些,2-4倍的差别比较正常
3 参数为引用类型动态代码的时间只是new的2倍多,而参数为值类型时倍数则较多,这是因为参数为引用类型时在从数组中取值之后需要一个拆箱操作,显然此操作是非常慢的。
4 调用动态代码时参数个数不同时所需时间也会增加,这个和预想的一样,因为由动态生成代码的部分可以看出,参数越多for循环执行的次数也越多,生成的IL代码就越长。
5 代码执行时间并不随参数的个数成倍数关系增长,这里大概因为从数组中取值的速度比较快,而newobj指令是最慢的,因此参数个数的影响不是很大。但参数为值类型时,时间增长的较快,这更说明了拆箱操作是很慢的,对结果的影响较大
6 参数为一个值类型时比参数为一个引用类型时动态代码所用的时间更短(值类型时为1937.5),引用类型时为(2312.5),但直观想象的话应该是引用类型的快一些才对,因为它不需要拆箱,并且拆箱也是个慢操作,但这与测试结果不符,我还不太清楚这是为什么。
7因同一段代码返复测试时时间也会有一些浮动,因此可以认为各种不同参数时new方法的时间几乎没有差别,可见像ldstr、ldc.i4这样的压栈操作速度是非常快的,相对于newobj来说几乎可以忽略不计。
相关文章推荐
- 对《基于动态代码生成技术的动态对象工厂》一文的补充
- 基于动态代码生成技术的动态对象工厂
- 基于动态代码生成技术的动态对象工厂
- 基于动态代码生成技术的动态对象工厂
- 基于动态代码生成技术的动态对象工厂
- 借助动态代码生成技术在基于Webkit引擎的HTML5网页JS内调用易语言函数
- java 代码动态生成技术相关文章合集
- YbSoftwareFactory 代码生成插件【九】:基于JQuery、WebApi的ASP.NET MVC插件的代码生成项目主要技术解析
- Android学习笔记_31_通过后台代码生成View对象以及动态加载XML布局文件到LinearLayout
- 基于 Eclipse 平台的代码生成技术
- java反射并不是什么高深技术,面向对象语言都有这个功能,而且功能也很简单,就是利用jvm动态加载时生成的class对象
- Android学习笔记_31_通过后台代码生成View对象以及动态加载XML布局文件到LinearLayout
- 基于 Eclipse 平台的代码生成技术
- 一起谈.NET技术,从数据到代码—基于T4的代码生成方式
- 第12章 动态代码生成和编译技术
- 分享一段C#反射代码-[Type是反射的入口]--[查看类型信息]--[动态生成对象]
- C++动态对象生成技术
- 基于JAVA动态编译的高性能对象序列化技术
- 基于JQuery、WebApi的ASP.NET MVC插件的代码生成项目主要技术解析
- 基于Java模板技术动态生成Word文档