Click here to Skip to main content
16,021,041 members
Articles / Programming Languages / C#
Article

Pre-compile (pre-JIT) your assembly on the fly, or trigger JIT compilation ahead-of-time

Rate me:
Please Sign up or sign in to vote.
4.91/5 (83 votes)
27 Nov 2008CPOL3 min read 155.3K   117   36
This article describes how to easily trigger pre-JITting of your heavy assemblies.

Introduction

All .NET developers know that one of the best features of the CLR is JIT-compilation: Just-In-Time compilation. Its name describes how it works: right before calling your method (just in time), the CLR triggers the JIT-compiler to produce native code from MSIL. JIT compilation is perfect for server-side applications: the JIT compiler produces highly optimized native code based on the execution environment data. The generated native code is stored in the application domain, and is used during consequent calls to this method. Though JIT compilation is not always the best choice for client-side applications with a rich user interface - users are pretty often complaining about lazy start-up of applications. In spite of developer explanations like "guys, it's JITting, we can't do anything here", users continue to complain, making our development managers unhappy. Obviously, unhappy managers tend to be unhappy developers.

So, what is the solution here? Develop the client-side application in C++ or Delphi? Some might say that we could use the Native Image Generation tool in .NET (ngen.exe). ngen.exe is not a silver bullet here, due to the following reasons:

    1. MSDN states regarding native images: Performance of native images depends on a number of factors that make analysis difficult, such as code and data access patterns, how many calls are made across module boundaries, and how many dependencies have already been loaded by other applications. The only way to determine whether native images benefit your application is by careful performance measurements in your key deployment scenarios. Let me rephrase this: it means that it does not guarantee you better performance.

    2. Native images installation/creation requires administrative privileges. This slightly reduces the set of suitable scenarios.

So, suddenly, I've come to the main point of my article. The main point is how to trigger JIT compilation in advance, how to pre-compile your assembly when it's more preferable for your application.

Let me start from an example:

Consider a scenario: We have a rich desktop client application with a huge number of different forms and and fancy UI controls (like DevExpress or Infragistics). Of course, during the first opening of each form, users are going to experience a delay due to JITting of all these fancy control libraries. How can we avoid this? We can trigger JIT compilation of heavy UI control libraries at some starting point of the application (for instance, during user log-in) in a separate background thread with a low priority. Or, we can pre-JIT all other forms while the user is working with the first one... I can imagine here a lot of Use Cases, but I am sure you can do it better in the scope of your particular project.

The code

We have a very nice namespace in BCL called System.Runtime.CompilerServices which provides advanced developers with the ability to influence runtime behavior. But, here, we need only one class from this namespace - RuntimeHelpers, and its method PrepareMethod, in particular. So, what do we do here: I just load some heavy assembly by using the Assembly.Load method (you can load it in a different way, of course), then walk through its types, and force JITting of all the methods of each type. That's it. As easy as possible. One more point, I do it in a separate low priority thread: don't worry about it, PrepareMethod is thread safe.

C#
Thread jitter = new Thread(() =>
{
  foreach (var type in Assembly.Load("MyHavyAssembly, Version=1.8.2008.8," + 
           " Culture=neutral, PublicKeyToken=8744b20f8da049e3").GetTypes())
  {
    foreach (var method in type.GetMethods(BindingFlags.DeclaredOnly | 
                        BindingFlags.NonPublic | 
                        BindingFlags.Public | BindingFlags.Instance | 
                        BindingFlags.Static))
    {
      System.Runtime.CompilerServices.RuntimeHelpers.PrepareMethod(method.MethodHandle);
    }
  }
});
jitter.Priority = ThreadPriority.Lowest;
jitter.Start();

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Technical Lead bwin Interactive Entertainment AG
Austria Austria
The views expressed in my articles are mine and do not necessarily reflect the views of my employer.

if(youWantToContactMe)
{
SendMessage(string.Format("{0}@{1}.com", "liptchinski_vit", "yahoo"));
}

More info in my LinkedIn profile:
http://www.linkedin.com/in/vitaliyliptchinsky

Comments and Discussions

 
QuestionNo increase in the performance Pin
kaliprasad12318-Jun-18 2:06
kaliprasad12318-Jun-18 2:06 
SuggestionWhat About Dynamic Assemblies IL uses? Pin
KOUKOSDD4-Mar-15 13:15
KOUKOSDD4-Mar-15 13:15 
GeneralMy vote of 5 Pin
Super Lloyd4-Apr-11 16:18
Super Lloyd4-Apr-11 16:18 
GeneralGreat post Pin
Andriy Buday14-May-10 13:10
Andriy Buday14-May-10 13:10 
GeneralComments Pin
Dmitri Nеstеruk18-Dec-08 4:24
Dmitri Nеstеruk18-Dec-08 4:24 
GeneralRe: Comments Pin
Vitaliy Liptchinsky18-Dec-08 4:53
Vitaliy Liptchinsky18-Dec-08 4:53 
GeneralError Pin
Uwe Keim14-Dec-08 22:35
sitebuilderUwe Keim14-Dec-08 22:35 
GeneralRe: Error Pin
Vitaliy Liptchinsky15-Dec-08 0:13
Vitaliy Liptchinsky15-Dec-08 0:13 
GeneralRe: Error Pin
Uwe Keim15-Dec-08 1:18
sitebuilderUwe Keim15-Dec-08 1:18 
GeneralRe: Error Pin
Uwe Keim15-Dec-08 1:26
sitebuilderUwe Keim15-Dec-08 1:26 
GeneralRe: Error Pin
Chris Richner18-Dec-08 4:00
Chris Richner18-Dec-08 4:00 
GeneralRe: Error Pin
Vitaliy Liptchinsky18-Dec-08 4:05
Vitaliy Liptchinsky18-Dec-08 4:05 
GeneralRe: Error Pin
Chris Richner20-Dec-08 2:59
Chris Richner20-Dec-08 2:59 
GeneralA very useful post, thanks - you might consider the following Pin
Neil Lamka3-Dec-08 13:14
Neil Lamka3-Dec-08 13:14 
GeneralCompiler as Service... Pin
Mohib Sheth2-Dec-08 17:50
Mohib Sheth2-Dec-08 17:50 
GeneralRe: Compiler as Service... Pin
Abel Braaksma25-Mar-12 10:42
Abel Braaksma25-Mar-12 10:42 
GeneralNice solution Pin
cokkiy2-Dec-08 1:49
cokkiy2-Dec-08 1:49 
GeneralThanks + Comments [modified] Pin
ittay ophir1-Dec-08 21:49
ittay ophir1-Dec-08 21:49 
GeneralRe: Thanks + Comments Pin
Vitaliy Liptchinsky1-Dec-08 21:55
Vitaliy Liptchinsky1-Dec-08 21:55 
GeneralRe: Thanks + Comments Pin
ittay ophir1-Dec-08 22:40
ittay ophir1-Dec-08 22:40 
GeneralRe: Thanks + Comments Pin
Vitaliy Liptchinsky1-Dec-08 23:11
Vitaliy Liptchinsky1-Dec-08 23:11 
GeneralRe: Thanks + Comments Pin
ittay ophir1-Dec-08 22:46
ittay ophir1-Dec-08 22:46 
GeneralRe: Thanks + Comments Pin
User 46119963-Dec-08 5:08
User 46119963-Dec-08 5:08 
GeneralERRORS Pin
seeblunt28-Nov-08 2:08
seeblunt28-Nov-08 2:08 
GeneralRe: ERRORS Pin
Nicola Costantini28-Nov-08 2:41
Nicola Costantini28-Nov-08 2:41 
better....

foreach (Type type in Assembly.Load(asm.FullName).GetTypes())
{
if (type.ContainsGenericParameters)
continue;

Smile | :)

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.