.NET下几种动态生成代码方式比较
场景:
平时在日常工作中往往会遇到这样的情况:一般的解决方案性能不是最好的,但性能最好的解决方案往往又不一定容易理解。如何兼顾这两者呢?这里有一个Microsoft网站上的例子,它用了几种动态代码生成的方法去实现同一个问题,可以对它们的性能做一个简单的比较,以后到底用那种方法心中就有数了。
要解决的问题:
计算一个多项式的值:
Y = A0 + A1 * X + A2 * X2 + … + An * Xn
比较指标:
1. 参数只有一个的情况: A0=5.5
2. 参数只有7个的情况: A0=5.5 A1=7.0 A2=15 A3=30 A4=500 A5=100 A6=1
3. 参数有30个的情况:A0=0 A1=1 ... A29=29
4. 参数有50个的情况:A0=0 A1=1 ... A49=49
5. 参数有100个的情况:A0=0 A1=1 ... A99=99
实现方式:
最普通的用循环的实现方式:(不涉及动态编程的内容,参考作用)
对参数进行循环。
显然这样的方式循环是很多的,这里对参数循环,外面还要对指数幂循环。为了减少循环的次数,考虑将上面Evaluate的方法用动态代码的方式实现。
有以下几种动态代码的实现方式:
1. <<PolyCodeSlow.cs>>
步骤:
a.用文件方式动态编写一个类来实现Evaluate方法;
b.动态编译生成DLL;
c.通过反射的方式来调用结果;
动态生成类的文件如下:(参数为7的情况)
2.<<PolyCode.cs>>
基本思路和上面一样,但稍有不同的是动态编写的类实现了接口。
a.用文件方式动态编写一个类来实现Evaluate方法,并且实现接口;
b.动态编译生成DLL;
c.通过接口来调用结果;
3.<<PolyCodeDom.cs>>
基本思路和2相同,但动态生成类的方法不同。
a.用CodeDom来动态编写一个类来实现Evaluate方法,并且实现接口;
b.动态编译生成DLL;
c.通过接口来调用结果;
4.<<PolyEmit.cs>>
这里直接用元编程技术,跳过文本编译生成的过程,直接生成动态编译结果然后调用。
a.建立动态程序集;
b.元编程技术实现动态类和方法;
c.通过动态类的接口调用结果;
结果比较: (数据是在机子上某次运行的结果)
动态代码花费的时间(主要花费在代码编译上)
花费时间(s) | 1个参数 | 7个参数 | 30个参数 | 50个参数 | 100个参数 |
一般代码方式(PolySimple.cs) | 0 | 0 | 0 | 0 | 0 |
动态代码方式一(PolyCodeSlow.cs) | 0.49 | 0.37 | 0.34 | 0.34 | 0.36 |
动态代码方式二(PolyCode.cs) | 0.47 | 0.4 | 0.36 | 0.37 | 0.43 |
动态代码方式三(PolyCodeDom.cs) | 0.51 | 0.38 | 0.43 | 0.39 | 0.38 |
动态代码方式四(PolyEmit.cs) | 0.01 | 0 | 0 | 0 | 0 |
每秒可以运行多少个表达式(性能比较)
1个参数 | 7个参数 | 30个参数 | 50个参数 | 100个参数 | |
一般代码方式(PolySimple.cs) | 24844149 | 10976159 | 3606267 | 2107176 | 1050327 |
动态代码方式一(PolyCodeSlow.cs) | 59905 | 59525 | 58981 | 57860 | 56057 |
动态代码方式二(PolyCode.cs) | 80258857 | 11703214 | 2973909 | 1930444 | 980942 |
动态代码方式三(PolyCodeDom.cs) | 113636349 | 11001798 | 2960087 | 1917754 | 769594 |
动态代码方式四(PolyEmit.cs) | 113636349 | 11916722 | 2935906 | 1925118 | 859074 |
由此可见:
后面三种动态方式的性能差不多,虽然元编程不花费时间在编译上,但其技术难度相对也高些。
本文转自风前絮~~博客园博客,原文链接:http://www.cnblogs.com/windsails/archive/2004/09/10/41756.html,如需转载请自行联系原作者