Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 编译表达式的运行速度比解释版本慢得多_C#_Performance_Jit_Precompiled - Fatal编程技术网

C# 编译表达式的运行速度比解释版本慢得多

C# 编译表达式的运行速度比解释版本慢得多,c#,performance,jit,precompiled,C#,Performance,Jit,Precompiled,我有一个规则引擎,它支持两种操作模式: 编译成C#程序并链接到引擎 解析为基于反向波兰堆栈的指令并进行解释 规则是带有函数调用(max、min、sin、cos等)的简单算术表达式 我会假设编译版本(即#1)比解释版本(即#2)快得多——事实上,这是拥有编译模式的首要原因。然而,我的速度测试显示了另一种情况 编译版本 这里,“表达式”是第三方库的一部分,该库将简单字符串解析为一组简单的基于反向波兰堆栈的指令,然后可以对其进行解释。它不是LINQ中的表达式树对象——只是为了澄清 注意:不要担心并发性

我有一个规则引擎,它支持两种操作模式:

  • 编译成C#程序并链接到引擎
  • 解析为基于反向波兰堆栈的指令并进行解释
  • 规则是带有函数调用(max、min、sin、cos等)的简单算术表达式

    我会假设编译版本(即#1)比解释版本(即#2)快得多——事实上,这是拥有编译模式的首要原因。然而,我的速度测试显示了另一种情况

    编译版本 这里,“表达式”是第三方库的一部分,该库将简单字符串解析为一组简单的基于反向波兰堆栈的指令,然后可以对其进行解释。它不是LINQ中的表达式树对象——只是为了澄清

    注意:不要担心并发性,因为在实际代码中,我按“层”对规则进行排序,并按顺序计算层,每个层仅取决于在以前的层中计算的值。两种模式具有完全相同的层结构

    结果 令人震惊的是,解释版本的运行速度比编译版本快得多,平均为4倍!换句话说,编译后的版本需要0.3秒来运行大约1200条规则,而解释后的版本平均需要0.08-0.1秒

    我的电脑是双核Core2

    我正在使用.NET4.0和VisualStudio10

    调试或发布版本中的性能类似

    我的问题 是什么导致编译模式的显著减速


    注意:我已经发布了一个可能的答案.NET是一个JIT编译环境,所以JIT编译的代码越多,它的速度就越慢。可能有1200个方法是在执行点的运行时进行JIT编译的,而在解释模式下,只有解释器进行一次JIT编译。我可能会在编译模式的循环中看到额外的JIT时间

    实验:

  • 每种模式运行5次(只是为了完成任何JIT编译并填充缓存)
  • 时间50次,取平均值
  • 结果:

  • 编译模式:每次运行1.6ms
  • 解释模式:每次运行5.3ms
  • 意见:

    在编译模式的第一次运行期间,似乎花费了大量时间

    编译模式的第二次运行在速度上已经与解释模式相似

    解释模式不会随着运行次数显著加快


    因此,我认为规则代码是在第一次运行时JIT编译的。

    这里的“Evaluate”方法是什么?我在MSDN上看不到表达式。表达式是否有
    求值方法?我不认为我们可以说得太有意义,除非我们有一些可以运行的东西,我们可以看一下……另外,请注意,大多数“运行”表达式的代码实际上是在编译它——因此它不是真正的解释,尽管编译可能会有一些开销。但最终,如果没有一个完整的例子,很难说得太多。“表达式”是用于解析表达式的自定义库。它将表达式解析为基于反向波兰堆栈的简单指令,然后对其进行解释。对不起,需要更多关于规则的详细信息以及如何解释这些规则。i、 e.您是否可以扩展一些ellipsisesRegular.NET方法,这些方法是根据需要进行JIT编译的,因此第一次调用某个方法时,会产生与编译相关的开销。
    
    Action<double>[] Rules = new[] { calc1, calc2, calc3 ... };
    double[] v = new double[...];   // Variables
    
    void calc1(double arg) { v[3]=v[12]+v[15]/v[20] };   // "x3=x12+x15/x20"
    void calc2(double arg) { ... };
       :
    // Start timer now
    Rules.AsParallel().ForAll(r => r(...));
    // End timer
    
    Expression[] Rules = ...
    // Each rule is already parsed into an Expression object, which is a set of
    // reverse-polish stack-based instructions.
    // For example, "x3=x12+x15/x20" will be parsed to:
    //     [ Push(12), Push(15), Push(20), Divide(), Add() ]
    // Start timer now
    Rules.AsParallel().ForAll(r => r.Evaluate(...));
    // End timer