Aidan Ryan
Aidan Ryan

Reputation: 11607

Why is DynamicMethod so much slower on x64?

I have a WCF service that uses LINQ to SQL for its data layer. Only stored procedures are in use, no dynamic table access. When I target x64, I am getting half the throughput of an x86 build. I have traced the hot path to Reflection.Emit.DynamicMethod.CreateDelegate. I created a simple test project to demonstrate the difference in performance between the two platforms.

What is the specific explanation for DynamicMethod being so much slower on x64? My vague understanding is that there may be an additional thunk involved in DynamicInvoke on x64.


Here are the results when performed on Windows 7 Enterprise x64, Core i7 Q720 @ 1.60 GHz, single-threaded:

Build Target      Average milliseconds to execute 100,000 iterations
x86               5504
x64               14699
Any CPU           14789

And the test code:

class Program
{
    private delegate string XInvoker(string arg);

    private const int OUTER_ITERATIONS = 4;
    private const int INNER_ITERATIONS = 100000;

    static void Main(string[] args)
    {
        Console.WriteLine("Timing {0} iterations, repeat {1} times...", INNER_ITERATIONS, OUTER_ITERATIONS);

        var watch = new Stopwatch();
        long totalMs = 0;

        for (int outer = 0; outer < OUTER_ITERATIONS; outer++)
        {
            watch.Restart();

            for (int inner = 0; inner < INNER_ITERATIONS; inner++)
            {
                var method = new DynamicMethod("X", typeof(string), new[] { typeof(string) });

                var ilGen = method.GetILGenerator();
                ilGen.Emit(OpCodes.Ldarg_0);
                ilGen.Emit(OpCodes.Ret);

                var del = method.CreateDelegate(typeof(XInvoker));
                var blah = del.DynamicInvoke("blah");
            }

            watch.Stop();
            totalMs += watch.ElapsedMilliseconds;

            Console.WriteLine("Took {0} ms to iterate {1} times", watch.ElapsedMilliseconds, INNER_ITERATIONS);
        }

        Console.WriteLine();
        Console.WriteLine("Overall average: {0} ms to iterate {1} times", totalMs / OUTER_ITERATIONS, INNER_ITERATIONS);
    }
}

Upvotes: 2

Views: 460

Answers (1)

AaronLS
AaronLS

Reputation: 38394

I would guess it's to do with the speed of compilation. There are lots of threads that seem to indicate JIT compiling for x64 is significanltly slower than x86.

In this one case someone saw significant performance increase in their x64 JIT just because other dependent assemblies weren't NGEN'd. Although I doubt it would help in this scenario, you never know what other things it is trying to load that might be slowing it down. Perhaps try running the command in the answer and see if that changes your performance. WPF slow to start on x64 in .NET Framework 4.0

Upvotes: 1

Related Questions