我有一个规则引擎,它支持两种操作模式:
。
规则是带有函数调用(max、min、sin、cos等)的简单算术表达式。
我会假设编译版本(即#1)是,比解释版本(即#2)快得多--事实上,这是首先采用编译模式的主要原因。然而,我的速度测试表明并非如此。
编译版本
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在这里,“表达式”是第三方库的一部分,该库将一个简单的字符串解析为一组简单的反波兰堆栈指令,然后可以对其进行解释。它不是LINQ中的表达式--树对象--只是为了澄清。
注意:不要担心并发性,因为在实际代码中,我按“层”对规则进行排序,并按顺序计算各层,每个层仅取决于在前几层中计算的值。这两种模式具有完全相同的层结构。
结果
令人震惊的是,解释版本运行的速度比编译版本快得多,平均是4倍!换句话说,编译后的版本需要用0.3s来运行大约1,200条规则,而解释版本平均需要0.08-0.1s。
我的电脑是一个如此双核的Core2。
我使用的是.NET 4.0,10。
在调试或发布版本中,性能是相似的。
我的问题
是什么导致了编译模式的显著放缓?
注意:我已经发布了一个可能的答案,
发布于 2011-05-11 12:16:53
.NET是一个JIT编译的环境,所以JIT编译的代码越多,它就越慢。可能有1,200个方法在执行时运行时是JIT编译的,而在解释模式下只有JIT编译了一次。我可能在编译模式的循环中看到了额外的JIT时间。
实验:
结果:
run
意见:
看来,在编译模式的第一次运行期间花费了大量时间。
编译模式的第二次运行速度已经与解释模式相似。
解释模式不会随着运行次数的增加而显著加快。
因此,我认为在第一次运行期间,规则代码是JIT编译的。
https://stackoverflow.com/questions/5963649
复制相似问题