gpt4 book ai didi

c# - 使用 CSharpCodeProvider 进行缓慢的动态编译

转载 作者:太空宇宙 更新时间:2023-11-03 21:51:27 26 4
gpt4 key购买 nike

我试图将动态编译与标准编译进行比较。而且动态编译好像慢了很多。根据我的基准测试,慢了 1400%。

下面是生成调用动态编译代码的委托(delegate)的方法:

public static Function Eval(string sCSCode)
{
CSharpCodeProvider c = new CSharpCodeProvider();
ICodeCompiler icc = c.CreateCompiler();
CompilerParameters cp = new CompilerParameters();

cp.ReferencedAssemblies.Add("system.dll");

cp.CompilerOptions = "/optimize";
//cp.GenerateInMemory = true;
StringBuilder sb = new StringBuilder("");

sb.Append("using System;\n");

sb.Append("namespace CSCodeEvaler{ \n");
sb.Append("public class CSCodeEvaler{ \n");
sb.Append("public double sin(double x) { return Math.Sin(x); }");
sb.Append("public double cos(double x) { return Math.Cos(x); }");
sb.Append("public double sqrt(double x) { return Math.Sqrt(x); }");
sb.Append("public const double PI = Math.PI;");
sb.Append("public double Calculate(double x, double y){\n");
sb.Append("return " + sCSCode + "; \n");
sb.Append("} \n");
sb.Append("} \n");
sb.Append("}\n");

CompilerResults cr = icc.CompileAssemblyFromSource(cp, sb.ToString());
if (cr.Errors.Count > 0)
{
throw new Exception("ERROR: " + cr.Errors[0].ErrorText);
return null;
}

System.Reflection.Assembly a = cr.CompiledAssembly;
object o = a.CreateInstance("CSCodeEvaler.CSCodeEvaler");
Type t = o.GetType();
MethodInfo mi = t.GetMethod("Calculate");

return delegate(double x, double y)
{
object[] oParams = new object[2];
oParams[0] = x;
oParams[1] = y;
object s = mi.Invoke(o, oParams);
return (double)s;
};
}

这是我为测试其性能而创建的代码:

private double f1(double x, double y)
{
return Math.Sin(x) + Math.Cos(y);
}

private void button1_Click(object sender, EventArgs e)
{
double sum = 0;
long t1 = DateTime.Now.Ticks;
for (double x = 0; x <= 500; x += 0.1)
{
for (double y = 0; y <= 500; y += 0.1)
{
sum += f1(x, y);
}
}
t1 = DateTime.Now.Ticks - t1;

sum = 0;
var f2 = FunctionConstructor.Eval("Math.Sin(x) + Math.Cos(y)");
long t2 = DateTime.Now.Ticks;
for (double x = 0; x <= 500; x += 0.1)
{
for (double y = 0; y <= 500; y += 0.1)
{
sum += f2(x, y);
}
}
t2 = DateTime.Now.Ticks - t2;
long dt = t2 - t1;
double q = dt / (double)t1;
MessageBox.Show("WITHOUT dynamic compilation: " + t1 + "\n" + "WITH dynamic compilation: " + t2 + "\n" + "Calculation without dynamic compilation was " + dt + " ticks (" + (q-1)*100 + "%) slower");
}

根据我的测试,动态编译要慢得多。这能以某种方式解决吗?也许问题出在我进行基准测试的方式上?

最佳答案

您正在调用一个花费非常时间的方法。这使得调用方法的开销成为影响代码速度的主要因素。动态调用和无法内联方法都是时间 killer 。您可以通过在 Calculate 方法中移动内部循环来查看差异。例如:

    sb.Append("public double Calculate(double x, double y){\n");
sb.Append("double sum = 0; for (; y <= 500; y += 0.1) {\n");
sb.Append("sum += " + sCSCode + ";\n");
sb.Append("} return sum;\n");

    long t2 = DateTime.Now.Ticks;
for (double x = 0; x <= 500; x += 0.1) {
sum += f2(x, 0);
}
t2 = DateTime.Now.Ticks - t2;

您会发现差异消失了。对此没有简单的解决方法。问题不完全在于动态调用代码很慢,而是允许抖动优化器生成最佳机器代码使其速度如此之快。这当然是一项功能,而不是错误。

关于c# - 使用 CSharpCodeProvider 进行缓慢的动态编译,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14338738/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com