Развлекаюсь тестируя разные извращения.
Вот такой простой код, который генерит, код, который подставит прямой адрес функции
Я не могу, посмотреть ассемблер сгенерированного кода, но представляю что там одна инструкция перехода с абсолютным адресом. Тогда как вызов по делегату, это вычисление адреса перед вызовом.
И предполагаю что будет быстрее,
а она медленее в 10 раз. В 10 раз как так,(при этом работает)
((delegate*<void>)0x3232332299060u)(); // псевдокод
c->action();
Почему первый способ работает в 3-10 раз медленнее?
//;# ((delegate*<void>)0x3232332299060u)();
IL_0000: ldc.i8 883059002544224
IL_0009: conv.u
IL_000a: calli void()
// инструкций меньше, есть константы, значит типа должно быть быстрее, но почему нетак
//;# c->action();
IL_000f: ldarg.0
IL_0010: ldind.ref
IL_0011: ldfld class [System.Runtime]System.Action C::action
IL_0016: callvirt instance void [System.Runtime]System.Action::Invoke()
IL_001b: ret
Код который творит такую ересь
void createSafe(Env*e){
// тут к примеру вообще вызов по делегату, что ну уж точно медленнее должно быть
var dm = new DynamicMethod("_1", null, new Type[] { typeof(Env).MakePointerType() });
var il = dm.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldfld, GetSafeHandlerField());
il.Emit(OpCodes.Callvirt, typeof(Action).GetMethod("Invoke", Type.EmptyTypes));
il.Emit(OpCodes.Ret);
return dm.CreateDelegate<EnvHandler>();
}
unsafe void createUnsafe(Env*e){
var dm = new DynamicMethod("_1", null, new Type[] { typeof(Env).MakePointerType() });
var il = dm.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldc_I8, typeof(Env).GetMethod("IncStatic").MethodHandle.GetFunctionPointer() );
il.EmitCalli(OpCodes.Calli, CallingConvention.Cdecl, null, new Type[] { typeof(Env*) });
il.Emit(OpCodes.Ret);
return dm.CreateDelegate<EnvHandler>();
}
struct Env{
int A;
static public unsafe void IncStatic(Env*e)
{
e->A++;
}
public Func<Env*> action=IncStatic;
}
При том разница в 10 раз!!!!!!!!!
Я предположу, что среда CLR не оптимизирует, не инлайнит, когда видит адрес в не пойми куда. или вообще там когда видит такой адрес, начинает проверять.
Ни где инфы не нашел.
(игрался со всеми конвенциями вызовов, и разным способом получения адреса функции, всегда медленнее)