The developer's toolkit for .NET: Part II: Cold Startup time
2. Application slow to load:
Scenario: “Our application takes too long to load for the first time. It exhibits the same behavior once in a while…”
To go ahead and analyze this scenario, we need to understand as to what happens when the application is loaded. Let me give a quick recap on that:
When we run any .NET application, the fusion loader first checks if native image of the assembly is available, if it is, then the loader loads the native image and skips the JITting (Just In Time) compilation. JIT can get time consuming and may take even few minutes depending on the size of the code in the assembly. This has obvious impact: the loading process will halt till the JIT finishes compiling the MSIL to the native code. The problem aggravates when there are multiple assemblies being loaded and JITted. So equally obvious solution would be to have native images readily generated so that when your application will load, it will use the native images.
.NET tools/Utilities we will use: Native Image Generator, NGEN.exe, and fusion log
How to troubleshoot:
1. As mentioned in the scenario statement, lets assume that your application takes say 2 min. to launch. In such scenarios, the first thing one should suspect is that the JIT is eating up the time and we should consider NGENing the assemblies. But before that, lets verify that the native images are not available. This steps is crucial. One must know that JITting is not the only one which can slow down the application load performace, there could be n other things which could hamper the load time performance for your application.
2. To verify that the native images are not available, we need to use the Fusion Log. Once you collect the fusion log, go to the log path and open the ‘NativeImage’ directory. This directory contains logs for all the assemblies and the logs will tell us if the Native image for the corresponding assembly is found or not. Here is the sample snippet of failure to find the native image:
*** Assembly Binder Log Entry (11/11/2008 @ 2:50:03 AM) ***
The operation failed.
Bind result: hr = 0x80070002. The system cannot find the file specified.
Assembly manager loaded from: C:\WINDOWS.0\Microsoft.NET\Framework64\v2.0.50727\mscorwks.dll
Running under executable E:\Innovation Day\Scenarios\FileNotFound\ConsoleApplication1\bin\Release\MainApplication.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: User = FAREAST\chancha
LOG: DisplayName = Dependency, Version=1.0.0.0, Culture=neutral, PublicKeyToken=12a0ae92d0a8861a
(Fully-specified)
LOG: Appbase = file:///E:/Innovation Day/Scenarios/FileNotFound/ConsoleApplication1/bin/Release/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = MainApplication.exe
Calling assembly : MainApplication, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.
===
LOG: Start binding of native image Dependency, Version=1.0.0.0, Culture=neutral, PublicKeyToken=12a0ae92d0a8861a.
WRN: No matching native image found.
3. Now that we know that the loader failed to find the native image, we know that the assembly is getting JITted. Hence our next action plan would be to generate the native image of all assemblies for which the loader failed to locate the native images.
4. To generate the native image .NET framework provides the utility named NGEN.exe. You can locate this executable in the framework directory (c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\). Here is the command syntax you will need to use:
a. To generate the native image:
NGEN install assemblyname
b. To delete the native image previously generated:
NGEN uninstall assemblyname
5. Now that we NGENed our assembly, lets run the application again and we should notice that the application now loads much faster, Bingo!!
All native images are actually stored in a centralized repository named ‘NGEN Cache’. You can use command window to browse to the NGEN Cache, the typical location would be: C:\WINDOWS\assembly\NativeImages_v2.0.50727_32.
In my next post, I’m going to talk about a dll named SoS.dll which is again shipped as part of .NET framework. This dll extends the Visual Studio Debugger (or for that matter, any debugger) to make it understand the Managed Code and Managed Heap. More on this in the following post…
- Chandrashekhar Chaudhari
Technical Lead
Microsoft Developer Support VC++ and C#