Reputation: 1122
I measure code speed like this:
var sw = new Stopwatch();
sw.Start();
DoSomething();
sw.Stop();
AddLog("Method speed is (ms): "+sw.ElapsedMilliseconds);
But first call of DoSomething() is slow, because code is compiling. Workaround is measure speed of second call like this:
var sw = new Stopwatch();
DoSomething();
sw.Start();
DoSomething();
sw.Stop();
AddLog("Method speed is (ms): "+sw.ElapsedMilliseconds);
Is there way to precompile DoSomethig() without first call?
Upvotes: 7
Views: 3308
Reputation: 7804
The documentation does not unequivocally state so, but according to this article (among others) you can use the
RuntimeHelpers.PrepareMethod
to precompile a method.
To elaborate on my comment (aforementioned) here is a code sample:
static void WarmUp()
{
var handle = typeof (Program).GetMethod("DoSomething").MethodHandle;
RuntimeHelpers.PrepareMethod(handle);
}
Update
Here is a more generic (although somewhat-brittle) solution that will account for instance members too:
public static class MethodWarmerUper
{
public static void WarmUp(string methodName)
{
var handle = FindMethodWithName(methodName).MethodHandle;
RuntimeHelpers.PrepareMethod(handle);
}
private static MethodInfo FindMethodWithName(string methodName)
{
return
Assembly.GetExecutingAssembly()
.GetTypes()
.SelectMany(type => type.GetMethods(MethodBindingFlags))
.FirstOrDefault(method => method.Name == methodName);
}
private const BindingFlags MethodBindingFlags =
BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic |
BindingFlags.Instance | BindingFlags.Static;
}
Upvotes: 4
Reputation: 2745
The reason you are seeing this difference in time is because the runtime is compiling the method for execution before the first call, while when it is about to be called a second time, everything required for running the method has already been compiled. You can use ngen.exe for this task. It compiles il to native exe ahead of execution and will decrease your startup time.
For your specific scenario, I believe ngen.exe to be the right tool for the job, as it can be triggered as a post build event to compile your assemblies ahead of time and be ready when you need them. If you use PrepareMethod, then you will still have the delay JITing the methods when you run your tests, just not when actually calling them.
Upvotes: 0