.NET下几种动态生成代码方式比较

简介:

场景:

        平时在日常工作中往往会遇到这样的情况:一般的解决方案性能不是最好的,但性能最好的解决方案往往又不一定容易理解。如何兼顾这两者呢?这里有一个Microsoft网站上的例子,它用了几种动态代码生成的方法去实现同一个问题,可以对它们的性能做一个简单的比较,以后到底用那种方法心中就有数了。


要解决的问题:

计算一个多项式的值:
        Y = A0 + A1 * X + A2 * X+ … + An * Xn 



比较指标:

1. 参数只有一个的情况: A 0 =5.5 
2. 参数只有7个的情况: A 0 =5.5  A 1 =7.0  A 2 =15 A 3 =30 A 4 =500 A 5 =100 A 6 =1
3. 参数有30个的情况:A 0 =0 A 1 =1 ... A 29 =29 
4. 参数有50个的情况:A 0 =0 A 1 =1 ... A 49 =49 
5. 参数有100个的情况:A 0 =0 A 1 =1 ... A 99 =99 

实现方式:

       最普通的用循环的实现方式:(不涉及动态编程的内容,参考作用)
       对参数进行循环。

     public  override  double Evaluate( double value)
    {
         double retval = coefficients[0];

         double f = value;

         for ( int i = 1; i < coefficients.Length; i++)
        {
            retval += coefficients[i] * f;
            f *= value;
    
        }
         return(retval);
    }

       显然这样的方式循环是很多的,这里对参数循环,外面还要对指数幂循环。为了减少循环的次数,考虑将上面Evaluate的方法用动态代码的方式实现。


有以下几种动态代码的实现方式:
1. <<PolyCodeSlow.cs>>
步骤:
a.用文件方式动态编写一个类来实现Evaluate方法;
b.动态编译生成DLL;
c.通过反射的方式来调用结果;

动态生成类的文件如下:(参数为7的情况)

//  polynomial evaluator
//  Evaluating y = 5.5 + 7 X^1 + 7 X^2 + 7 X^3 + 7 X^4 + 7 X^5 + 7 X^6

class Poly_1
{
public  double Evaluate( double value)
{
     return(
        5.5
        + value * (7 
        + value * (15 
        + value * (30 
        + value * (500 
        + value * (100 
        + value * (1 
    )))))));
}
}


2.<<PolyCode.cs>>
基本思路和上面一样,但稍有不同的是动态编写的类实现了接口。
a.用文件方式动态编写一个类来实现Evaluate方法,并且实现接口;
b.动态编译生成DLL;
c.通过接口来调用结果;

//  polynomial evaluator
//  Evaluating y = 5.5 + 7 X^1 + 15 X^2 + 30 X^3 + 500 X^4 + 100 X^5 + 1 X^6

class Poly_1001: PolyInterface.IPolynomial
{
public  double Evaluate( double value)
{
     return(
        5.5
        + value * (7 
        + value * (15 
        + value * (30 
        + value * (500 
        + value * (100 
        + value * (1 
    )))))));
}
}


3.<<PolyCodeDom.cs>>
基本思路和2相同,但动态生成类的方法不同。
a.用CodeDom来动态编写一个类来实现Evaluate方法,并且实现接口;
b.动态编译生成DLL;
c.通过接口来调用结果;

//  Polynomial evaluator
//  Evaluating Y = 5.5 + 7 X^1 + 15 X^2 + 30 X^3 + 500 X^4 + 100 X^5 + 1 X^6
public  class Poly_1001 : PolyInterface.IPolynomial {
    
     public  double Evaluate(System.Double x) {
         return (5.5 
                    + (x 
                    * (7 
                    + (x 
                    * (15 
                    + (x 
                    * (30 
                    + (x 
                    * (500 
                    + (x 
                    * (100 
                    + (x 
                    * (1 + 0)))))))))))));
    }
}


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,如需转载请自行联系原作者

相关文章
|
JSON IDE 前端开发
[.NET开发者的福音]一个方便易用的在线.NET代码编辑工具.NET Fiddle
[.NET开发者的福音]一个方便易用的在线.NET代码编辑工具.NET Fiddle
126 0
|
网络协议 算法 Shell
来我们探究一下net/http 的代码流程
来我们探究一下net/http 的代码流程
173 0
【Azure 媒体服务】Media Service的编码示例 -- 创建缩略图子画面的.NET代码调试问题
【Azure 媒体服务】Media Service的编码示例 -- 创建缩略图子画面的.NET代码调试问题
|
C# 开发者 Windows
在VB.NET项目中使用C#编写的代码
在VB.NET项目中使用C#编写的代码
155 0
|
9月前
|
算法 Java 测试技术
使用 BenchmarkDotNet 对 .NET 代码进行性能基准测试
使用 BenchmarkDotNet 对 .NET 代码进行性能基准测试
210 13
|
9月前
|
开发框架 .NET PHP
ASP.NET Web Pages - 添加 Razor 代码
ASP.NET Web Pages 使用 Razor 标记添加服务器端代码,支持 C# 和 Visual Basic。Razor 语法简洁易学,类似于 ASP 和 PHP。例如,在网页中加入 `@DateTime.Now` 可以实时显示当前时间。
|
10月前
|
敏捷开发 缓存 中间件
.NET技术的高效开发模式,涵盖面向对象编程、良好架构设计及高效代码编写与管理三大关键要素
本文深入探讨了.NET技术的高效开发模式,涵盖面向对象编程、良好架构设计及高效代码编写与管理三大关键要素,并通过企业级应用和Web应用开发的实践案例,展示了如何在实际项目中应用这些模式,旨在为开发者提供有益的参考和指导。
104 3
|
11月前
|
前端开发 JavaScript C#
CodeMaid:一款基于.NET开发的Visual Studio代码简化和整理实用插件
CodeMaid:一款基于.NET开发的Visual Studio代码简化和整理实用插件
240 0
【Azure Key Vault】.NET 代码如何访问中国区的Key Vault中的机密信息(Get/Set Secret)
【Azure Key Vault】.NET 代码如何访问中国区的Key Vault中的机密信息(Get/Set Secret)
|
Kubernetes 监控 Devops
【独家揭秘】.NET项目中的DevOps实践:从代码提交到生产部署,你不知道的那些事!
【8月更文挑战第28天】.NET 项目中的 DevOps 实践贯穿代码提交到生产部署全流程,涵盖健壮的源代码管理、GitFlow 工作流、持续集成与部署、容器化及监控日志记录。通过 Git、CI/CD 工具、Kubernetes 及日志框架的最佳实践应用,显著提升软件开发效率与质量。本文通过具体示例,助力开发者构建高效可靠的 DevOps 流程,确保项目成功交付。
213 0