Why is Func<> created from Expression> slower than Func<> declared directly?

前端 未结 6 1751
囚心锁ツ
囚心锁ツ 2020-12-12 17:54

Why is a Func<> created from an Expression> via .Compile() considerably slower than just using a Func<>

6条回答
  •  被撕碎了的回忆
    2020-12-12 18:21

    As others have mentioned, the overhead of calling a dynamic delegate is causing your slowdown. On my computer that overhead is about 12ns with my CPU at 3GHz. The way to get around that is to load the method from a compiled assembly, like this:

    var ab = AppDomain.CurrentDomain.DefineDynamicAssembly(
                 new AssemblyName("assembly"), AssemblyBuilderAccess.Run);
    var mod = ab.DefineDynamicModule("module");
    var tb = mod.DefineType("type", TypeAttributes.Public);
    var mb = tb.DefineMethod(
                 "test3", MethodAttributes.Public | MethodAttributes.Static);
    expression.CompileToMethod(mb);
    var t = tb.CreateType();
    var test3 = (Func)Delegate.CreateDelegate(
                    typeof(Func), t.GetMethod("test3"));
    
    int counter3 = 0;
    Stopwatch s3 = new Stopwatch();
    s3.Start();
    for (int i = 0; i < 300000000; i++)
    {
        counter3 += test3(i).Value;
    }
    s3.Stop();
    var result3 = s3.Elapsed;
    

    When I add the above code, result3 is always just a fraction of a second higher than result1, for about a 1ns overhead.

    So why even bother with a compiled lambda (test2) when you can have a faster delegate (test3)? Because creating the dynamic assembly is much more overhead in general, and only saves you 10-20ns on each invocation.

提交回复
热议问题