Geeks With Blogs
Jeff Ferguson Irritating other people since 1967

You may find during application performance analysis that you can improve your application’s cold start time by using native images for both your application and its dependent assemblies. Native images will alleviate the need for your code to run through the CLR’s Just-In-Time (JIT) compiler at runtime.

If you go down this route, you will want to ensure that the native images are actually being loaded and that the JIT process is being bypassed. In general, you will follow a checklist like this:

  1. Add the application’s assemblies in the Global Assembly Cache with gacutil.
  2. Generate native images for the application’s assemblies using ngen.
  3. Run your application.
  4. While the application is still running, use tlist to find the process ID for the application’s process.
  5. While the application is still running, use vadump to see the list of modules loaded into the application’s process using a command line of vadump –sop [ProcessID].

You can see the native images loaded by the process list output by the vadump tool by looking for loaded modules with .ni. in the module name. If your application references System.Web, for example, and the assembly bind engine opts to bind to the assembly’s native image, you will see System.Web.ni.dll, rather than System.Web.dll, in the loaded module list.

You may discover times when the assembly was not loaded using its native image, even if you added the assembly to the GAC and created a native image. This may happen frequently if your application uses more than one application domain. Using the Fusion Log Viewer will help you discover why the binding behaved differently than you expected.

You can check the vadump loaded modules list for module names that reference the Intermediate Language version of the assembly (without the .ni. in the name) rather than the native image version of the assembly (with the .ni. in the name) that you expecting to see. In cases like this, start by looking at the Fusion binding log for the assembly in question. It may look something like this:

   1:  *** Assembly Binder Log Entry  (2/26/2010 @ 11:11:01 AM) *** 
   2:   
   3:  The operation failed. 
   4:  Bind result: hr = 0x80070002. The system cannot find the file specified. 
   5:   
   6:  Assembly manager loaded from:  c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\mscorwks.dll 
   7:  Running under executable  C:\Documents and Settings\Administrator\Desktop\MyApp.exe 
   8:  --- A detailed error log follows. 
   9:   
  10:  === Pre-bind state information === 
  11:  LOG: User = MY-MACHINE\Administrator 
  12:  LOG: DisplayName = MyCompany.MyProject.Namespace1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=XXXXXXXXXXXXXXXX 
  13:  (Fully-specified) 
  14:  LOG: Appbase = file:///C:/Documents and Settings/Administrator/Desktop/ 
  15:  LOG: Initial PrivatePath = NULL 
  16:  LOG: Dynamic Base = NULL 
  17:  LOG: Cache Base = NULL 
  18:  LOG: AppName = NULL 
  19:  Calling assembly : MyCompany.MyProject.Namespace2, Version=1.0.0.0, Culture=neutral, PublicKeyToken=XXXXXXXXXXXXXXXX. 
  20:  === 
  21:  LOG: Start binding of native image MyCompany.MyProject.Namespace1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=XXXXXXXXXXXXXXXX. 
  22:  LOG: Start validating native image MyCompany.MyProject.Namespace1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=XXXXXXXXXXXXXXXX. 
  23:  LOG: Start validating all the dependencies. 
  24:  LOG: [Level 1]Start validating native image dependency System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089. 
  25:  WRN: IL assembly is found in load context, but it has no native image. 
  26:  WRN: No matching native image found. 

Take a look at lines 25 and 26. According to this binding log entry, the assembly manager loaded the native image for the assembly, but the native image for the dependent System assembly failed to load.

Next, look at the Fusion binding log for the dependent assembly in question. In this case, you will need to check the entry for the System assembly. The assembly binding log for the System assembly will most likely reveal more information:

   1:  *** Assembly Binder Log Entry  (2/26/2010 @ 11:10:55 AM) *** 
   2:   
   3:  The operation was successful. 
   4:  Bind result: hr = 0x0. The operation completed successfully. 
   5:   
   6:  Assembly manager loaded from:  c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\mscorwks.dll 
   7:  Running under executable  C:\Documents and Settings\Administrator\Desktop\MyApp.exe 
   8:  --- A detailed error log follows. 
   9:   
  10:  === Pre-bind state information === 
  11:  LOG: User = MY-MACHINE\Administrator 
  12:  LOG: DisplayName = System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 
  13:  (Fully-specified) 
  14:  LOG: Appbase = file:///C:/Documents and Settings/Administrator/Desktop / 
  15:  LOG: Initial PrivatePath = NULL 
  16:  LOG: Dynamic Base = NULL 
  17:  LOG: Cache Base = NULL 
  18:  LOG: AppName = NULL 
  19:  Calling assembly : MyCompany.MyProject.Namespace3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=XXXXXXXXXXXXXXXX. 
  20:  === 
  21:  LOG: Start binding of native image System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089. 
  22:  LOG: Start validating native image System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089. 
  23:  LOG: Start validating all the dependencies. 
  24:  LOG: [Level 1]Start validating native image dependency mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089. 
  25:  LOG: Dependency evaluation succeeded. 
  26:  LOG: [Level 1]Start validating IL dependency System.Xml, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089. 
  27:  LOG: Dependency evaluation succeeded. 
  28:  LOG: [Level 1]Start validating IL dependency System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a. 
  29:  LOG: Dependency evaluation succeeded. 
  30:  LOG: Validation of dependencies succeeded. 
  31:  LOG: Start loading all the dependencies into load context. 
  32:  LOG: Loading of dependencies succeeded. 
  33:  LOG: Bind to native image succeeded. 
  34:  Native image has correct version information. 
  35:  Attempting to use native image C:\WINDOWS\assembly\NativeImages_v2.0.50727_32\System\3de5bd01124463d7862bd173af90bc83\System.ni.dll. 
  36:  ZAP: An ngen image of an assembly which is not loaded as domain-neutral cannot be used in multiple appdomains - abandoning ngen image. The assembly will be JIT-compiled in the second appdomain. See System.LoaderOptimization.MultiDomain for information about domain-neutral loading. 
  37:  Discarding native image. 

Take a look at lines 36 and 37. The assembly binding log reveals that assembly loader found the native image for the System assembly but had to discard it because, by the time this load request was issued, the native image for the System assembly had already been loaded into another application domain.

A native image can be loaded into only a single application domain unless the assembly was loaded as a domain-neutral assembly.

Since the assembly loader could not load the native image for the dependent System assembly, the native image for the original assembly fails to load, and the assembly binding falls back to loading the MSIL image.

You can specify how loaded assemblies interact with multiple application domains by using the LoaderOptimization attribute on an application’s Main() method:

   1:  [LoaderOptimization(LoaderOptimization.MultiDomainHost)] 
   2:  static void Main(string[] args) 
   3:  { 
   4:    ... 
   5:  } 

The LoaderOptimization accepts, as a parameter, an enumeration with one of three possible values:

  • SingleDomain: Loads no assemblies as domain-neutral, except mscorlib, which is always loaded domain-neutral. This setting is called single domain because it is commonly used when the host is running only a single application in the process. This is the default assembly domain loading scenario.
  • MultiDomain: Loads all assemblies as domain-neutral.
  • MultiDomainHost: Loads strong-named assemblies as domain-neutral if they and all their dependencies have been installed in the GAC. Other assemblies are loaded and JIT-compiled separately for each application domain in which they are loaded, and thus can be unloaded from the process.

You can also take advantage of the values in this enumeration when an application domain is created:

   1:  AppDomainSetup NewAppDomainSetup = new AppDomainSetup(); 
   2:  NewAppDomainSetup.LoaderOptimization = LoaderOptimization.MultiDomainHost; 
   3:  return AppDomain.CreateDomain("AppDomainName", null, NewAppDomainSetup); 
Posted on Monday, March 1, 2010 8:12 PM | Back to top


Comments on this post: Assembly Native Image Load Failures

# Native Image
Requesting Gravatar...
I keep getting this message pop-up. Is it legitimate?

C\Windows\assembly\NativeImages_v2.0.50727_32\SMSvcHost\3a42b2fbafe93d7b939se328bea35afa\SMSvcHost.ni.exe

Left by Joyce Sims on Apr 14, 2011 7:49 PM

# re: Assembly Native Image Load Failures
Requesting Gravatar...
Hello Joyce -- I am not sure I understand your question. Are you seeing a message box that simply contains the text "C\Windows\assembly\NativeImages_v2.0.50727_32\SMSvcHost\3a42b2fbafe93d7b939se328bea35afa\SMSvcHost.ni.exe"?
Left by Jeff Ferguson on Apr 15, 2011 7:14 AM

Your comment:
 (will show your gravatar)


Copyright © Jeff Ferguson | Powered by: GeeksWithBlogs.net