He leído varias publicaciones sobre SO sobre cómo escribir y compilar código dinámico de C#. Por ejemplo, this post. Entiendo que se puede hacer de varias maneras.Ejecuta el código C# compilado dinámicamente a la velocidad nativa ... ¿cómo?
Sin embargo, llamar al código invocador es lento. Hice un punto de referencia simple, y es unas 500 veces más lento que llamar a un método nativo.
Lo que quiero poder hacer es el equivalente a cargar un archivo DLL y llamar a uno de sus métodos directamente ("nativamente"), lo que dará los beneficios de velocidad que deseo.
¿Cuál es la forma más fácil de hacerlo? ¿Compila el código dinámico a un dll y luego lo carga? ¿Se puede hacer en la memoria?
EDITAR
no me importa el tiempo de compilación. Solo ejecución.
EDIT 2, 3
Aquí está el código de referencia que escribí:
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<int, int>) Delegate.CreateDelegate(typeof (Func<int, int>), 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<int, int> 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());
}
¿Has tenido en cuenta el tiempo de compilación? ¿cómo se ve su punto de referencia? – Botz3000
ejecutando C# build tiempo de ejecución no es 500 veces más lento que ejecutar C# build anterior. Son idénticos, sin embargo, hay gastos generales a considerar. ¿Cuál es su punto de referencia, está utilizando Reflection.Emit o algún servicio de compilación para compilar? –
La invocación es lo lento, que es el centro de mi pregunta: ¿cómo se puede llamar al método a velocidad nativa? – IamIC