Comments 13
Итак, в этом, на мой взгляд, заключается потенциал использования IL напрямую. Генерировать методы с его помощью, по-моему, занятие бесполезное, для этого есть более подходящие средства. Но вот модификация существующего кода IL может помочь в определенных ситуациях.
Expression'ы оказывается компилятся в нечто не самое быстрое, как всем может показаться. Цитата из статьи от Sergey Teplyakov:
Expression.Compile creates a DynamicMethod and associates it with an anonymous assembly to run it in a sandboxed environment. This makes it safe for a dynamic method to be emitted and executed by partially trusted code but adds some run-time overhead.
Поэтому, иногда генерация на IL вместо Expression оправдана.
+1
Да, я тоже это заметил. Решил проблему тем, что создавал сборку вручную, что-то вроде:
В этом случае падения производительности уже не наблюдалось, и смысла генерить IL-код просто не было. Заодно появилась возможность сохранить сборку в файл, посмотреть на IL-код и декомпилировать метод.
Код
public static class RuntimeBase
{
static AssemblyBuilder assembly_builder;
static ModuleBuilder module_builder;
static int next_id;
static RuntimeBase()
{
AssemblyName an = new AssemblyName("iplibdyn");
assembly_builder = AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.Save);
module_builder = assembly_builder.DefineDynamicModule("ImageLibGeneratedCode", "iplibdyn.dll", false);
next_id = 0;
}
public static T CompileExpressionToMethod<T>(LambdaExpression expression, string name)
where T : class
{
if (name == null)
name = string.Format("CLS{0}", ++next_id);
else
name = string.Format("CLS{0}_{1}", ++next_id, name);
TypeBuilder type_builder = module_builder.DefineType(name);
MethodBuilder method_builder = type_builder.DefineMethod("DynMethod", MethodAttributes.Public | MethodAttributes.Static);
try
{
expression.CompileToMethod(method_builder);
}
catch (Exception E)
{
Console.WriteLine("Exception: {0}{1}", E.Message, E.StackTrace);
Debugger.Break();
}
Type type = type_builder.CreateType();
MethodInfo mi = type.GetMethod("DynMethod");
return Delegate.CreateDelegate(typeof(T), mi) as T;
}
public static TypeBuilder DefineType(string name)
{
return module_builder.DefineType(name, TypeAttributes.Public);
}
public static void SaveDll()
{
assembly_builder.Save("iplibdyn.dll");
}
}
В этом случае падения производительности уже не наблюдалось, и смысла генерить IL-код просто не было. Заодно появилась возможность сохранить сборку в файл, посмотреть на IL-код и декомпилировать метод.
+2
Вы его замеряли этот " some run-time overhead"?
Это наносекунды.
Тут мой бенчмарк.
stackoverflow.com/questions/44239127/why-compiled-lambda-build-over-expression-call-is-slightly-slower-than-delegate
Это наносекунды.
Тут мой бенчмарк.
stackoverflow.com/questions/44239127/why-compiled-lambda-build-over-expression-call-is-slightly-slower-than-delegate
0
Нет, не наносекунды. У меня подобные методы — автосгенерированный код для обработки изображений, одна функция может работать несколько миллисекунд. Так вот разница была не наносекунды, а разы.
0
Упомянутая проверка перед вызовом из anonymous assembly — добавляет наносекунды. Benchmark приведен. Если проблема в том что у вас очень много вызовов (например в цикле и наносекунды накапливаются в миллисекунды) я бы решал проблему перенеся и цикл в anonymous assembly.
0
Это eval в C#?
+1
UFO just landed and posted this here
в С# в 2018 году изобрели метапрограмирование по данным от рефлексии?
-4
Слайды с кодом, особенно автосгенерированным, очень плохо читаются. И этот код нельзя скопировать.
0
Очень странно, что все это работает, потому что когда я спрашивал у команды как это сделать, мне сказали «низя by design». Подробности в этом issue.
0
Sign up to leave a comment.
Генерация кода во время работы приложения: реальные примеры и техники