C#学习教程:以原生速度运行动态编译的C#代码……怎么样?分享


以原生速度运行动态编译的C#代码……怎么样?

我已经阅读了几篇关于编写和编译动态C#代码的post。 例如, 这篇文章 。 我知道它可以通过几种方式完成。

但是,调用代码调用程序很慢。 我做了一个简单的基准测试,它比调用本机方法慢了约500倍。

我想要做的是相当于加载DLL并直接调用其中一个方法(“本机”),这将提供我想要的速度优势。

最简单的方法是什么? 将动态代码编译为dll然后加载它? 可以在记忆中完成吗?

编辑

我不关心编译时间。 只执行。

编辑2,3

这是我写的基准代码:

public static int Execute(int i) { return i * 2; } private void button30_Click(object sender, EventArgs e) { CSharpCodeProvider foo = new CSharpCodeProvider(); var res = foo.CompileAssemblyFromSource( new System.CodeDom.Compiler.CompilerParameters() { GenerateInMemory = true, CompilerOptions = @"/optimize", }, @"public class FooClass { public static int Execute(int i) { return i * 2; }}" ); var type = res.CompiledAssembly.GetType("FooClass"); var obj = Activator.CreateInstance(type); var method = type.GetMethod("Execute"); int i = 0, t1 = Environment.TickCount, t2; //var input = new object[] { 2 }; //for (int j = 0; j < 10000000; j++) //{ // input[0] = j; // var output = method.Invoke(obj, input); // i = (int)output; //} //t2 = Environment.TickCount; //MessageBox.Show((t2 - t1).ToString() + Environment.NewLine + i.ToString()); t1 = Environment.TickCount; for (int j = 0; j < 100000000; j++) { i = Execute(j); } t2 = Environment.TickCount; MessageBox.Show("Native: " + (t2 - t1).ToString() + Environment.NewLine + i.ToString()); var func = (Func) Delegate.CreateDelegate(typeof (Func), method); t1 = Environment.TickCount; for (int j = 0; j < 100000000; j++) { i = func(j); } t2 = Environment.TickCount; MessageBox.Show("Dynamic delegate: " + (t2 - t1).ToString() + Environment.NewLine + i.ToString()); Func funcL = Execute; t1 = Environment.TickCount; for (int j = 0; j < 100000000; j++) { i = funcL(j); } t2 = Environment.TickCount; MessageBox.Show("Delegate: " + (t2 - t1).ToString() + Environment.NewLine + i.ToString()); } 

是的,如果您通过MethodInfo或非特定的Delegate调用,那么它确实会很慢。 诀窍是: 不要那样做 。 各种方法:

如果您遇到任何类型的性能,请不要使用someDelegate.DynamicInvoke(...)someMethod.Invoke(...)

除了Marc的建议,你可以通过指定“optimize”编译器选项来提高速度:

 var res = foo.CompileAssemblyFromSource( new System.CodeDom.Compiler.CompilerParameters() { GenerateInMemory = true, CompilerOptions = "/optimize" }, 

认为值得展示所有潜在选项的外观及其性能特征。 给出以下帮助程序类和函数:

 public void Test(Func func) { var watch = new Stopwatch(); watch.Start(); for (var i = 0; i <= 1000000; i++) { var test = func(); } Console.WriteLine(watch.ElapsedMilliseconds); } public class FooClass { public int Execute() { return 1;}} 

设置和执行:

 using (Microsoft.CSharp.CSharpCodeProvider foo = new Microsoft.CSharp.CSharpCodeProvider()) { var res = foo.CompileAssemblyFromSource( new System.CodeDom.Compiler.CompilerParameters() { GenerateInMemory = true }, "public class FooClass { public int Execute() { return 1;}}" ); var real = new FooClass(); Test(() => real.Execute()); // benchmark, direct call var type = res.CompiledAssembly.GetType("FooClass"); var obj = Activator.CreateInstance(type); var method = type.GetMethod("Execute"); var input = new object[] { }; Test(() => (int)method.Invoke(obj, input)); // reflection invoke dynamic dyn = Activator.CreateInstance(type); Test(() => dyn.Execute()); // dynamic object invoke var action = (Func)Delegate.CreateDelegate(typeof(Func), null, method); Test(() => action()); // delegate } 

结果是:

 8 // direct 771 // reflection invoke 41 // dynamic object invoke 7 // delegate 

那么在那些你不能使用代表的情况下(如果你还不够了?),你可以试试dynamic

上述就是C#学习教程:以原生速度运行动态编译的C#代码……怎么样?分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—猴子技术宅(www.ssfiction.com)

本文来自网络收集,不代表猴子技术宅立场,如涉及侵权请点击右边联系管理员删除。

如若转载,请注明出处:https://www.ssfiction.com/ckf/1269673.html

(0)
上一篇 1天前
下一篇 1天前

精彩推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注