Wozart
Wozart

Reputation: 125

Preload all assemblies (JIT)

We are taking a hit the first time some heavy UI screens are loaded. Our project is divided into one main executable and several DLL files. The DLL files can also contain UI screens which are slow the first time they are loaded.

Is there a way (in code) we can preload all the referenced assemblies so as to avoid the JIT compilation hit?

I know there is a tool called NGen. Is it possible to operate NGen in a development environment so we can see its effects instantly? Ideally though, we would like to preload the referenced assemblies from code.

Using C# .NET 3.5 along with DevExpress for our UI components.

Upvotes: 5

Views: 10302

Answers (5)

Cameron
Cameron

Reputation: 3073

I personally found that putting the pre-jitter in 'Program' helped in a certain application, but that is a situation-specific question.

More importantly, the code in wal's answer will crash when it encounters an abstract method, so two lines of code have been added to skip abstract methods.

static Program()
{
    foreach (var type in Assembly.GetExecutingAssembly().GetTypes())
    {
        foreach (var method in type.GetMethods(BindingFlags.DeclaredOnly |
                            BindingFlags.NonPublic |
                            BindingFlags.Public | BindingFlags.Instance |
                            BindingFlags.Static))
        {
            if ((method.Attributes & MethodAttributes.Abstract) == MethodAttributes.Abstract|| method.ContainsGenericParameters)
            {
                continue;
            }
            System.Runtime.CompilerServices.RuntimeHelpers.PrepareMethod(method.MethodHandle);
        }
    }
    Console.WriteLine("jitted!");
}

Upvotes: 8

wal
wal

Reputation: 17749

Did you try/look at this?

That is, do the following for each assembly you want to pre JIT.

static void PreJIT()
{
    foreach (var type in Assembly.GetExecutingAssembly().GetTypes())
    {
        foreach (var method in type.GetMethods(BindingFlags.DeclaredOnly |
                            BindingFlags.NonPublic |
                            BindingFlags.Public | BindingFlags.Instance |
                            BindingFlags.Static))
        {
            System.Runtime.CompilerServices.RuntimeHelpers.PrepareMethod(method.MethodHandle);
        }
    }
}

Upvotes: 7

Alexei Levenkov
Alexei Levenkov

Reputation: 100545

You can use NGen on any machine - there is no notion of "development enviroment" in CLR... When you use it make sure that NGen'ed images are actually used (see Native Image Generator (Ngen.exe) for instructions and look for FusLogVw note in the document).

You can also pre-JIT through invoking all the code you expect to run (as Davita suggested), but you'll need to invoke each and every method of all classes which in not exactly practical.

You should profile your application to see where time is actually spent - it could be reading of the assemblies from the disk, not JITing itself... You can roughly see it by starting the application, looking at the forms, closing the application and repeating steps. If the second run is much faster then the application spends most of the time reading from the disk, not JITing.

Upvotes: 0

Bala R
Bala R

Reputation: 108977

Take a look at NGen. Another option is to use ILMerge to merge all your assemblies into one. Whenever I use ILMerge, I add a post build command to so it happens automatically. The other alternative (untested) is, if you don't mind a longer start-up time, you could manually call Assembly.Load() at the beginning for each assembly.

Upvotes: 6

Davita
Davita

Reputation: 9134

You can just create instances of the classes located in externall assemblies. Just call the constructor in a limited scope (I mean declare the variable inside a function. It should not be global var because it will delay GC to dispose that instance). This will load the assembly, compile it and cache it. You can even do this in a background thread so the main thread will keep responsiveness.

Upvotes: 1

Related Questions