tags:

views:

73

answers:

4

At my work, we are developing different applications using .net framework 4. All the applications use common assemblies that we developed, for example the data layer in data.dll. These applications reside on a network drive and are launched directly from there.

Most big applications take a while, like maybe 4-5 seconds, to launch the first time (cold startup). The subsequent launches are much faster, almost instantaneous. I don't think it has to do with the network, since the biggest assembly is around 900KB and we are using a Gigabit network.

I would like to create a service that starts when the computer starts, and that load all the .net assemblies under a specific directory. I am hoping that when the user launches a program, all the necessary assemblies will already be loaded and 'JITed', so the startup should be faster.

I know how to create a service, but I would like to know if this could work because my understanding of the CLR is pretty limited... Also, would doing something like Assembly.LoadFrom(fileName) work to preload the assemblies? If I don't launch any programs for a while, do they stay loaded or do they unload themselves after a while? What happens if I change an assembly that's already loaded?

Basically, I would like to do something like the OpenOffice Quick starter, but for our own application framework.

Thanks everyone!!!

---EDIT---
This is interresting... seems to go in the right way but not sure I understand everything ...

A: 

You have several options. Assuming the common assemblies have strong names, they can be placed in the user's Global Assembly Cache (GAC). If these assemblies are stable, you can have native code generated with ngen.exe, which will give you the "pre-JIT'd" you need. Google GAC and ngen for more info.

Edit after question update:

Loading assemblies in the way you're seeking isn't necessarily the most effective way - those assemblies will live in your service's memory for as long as the service is around, and that may or may not be a burden on the client machine.

I believe that a combination of GAC'ing and ngen'ing your assemblies is the best bet, and both of those steps can be automated (assuming the service is running with the appropriate permissions) by retrieving the assemblies and making external calls to gacutil.exe and ngen.exe using the System.Diagnostics.Process class.

MSDN page for ngen.exe

MSDN page for gacutil.exe

MSDN page for the Process class

Ben
Cannot put them in GAC because they reside on the network, and they are not really stable since we are still developping them...
Pierre-Olivier Goulet
In that case, I can't think of any way to avoid the hit of loading and JITing the assemblies at application runtime - I believe that non-GAC'd assemblies are not shared between app domains.
Ben
I think GACed assemblies are still not shared without specifying the load behavior (multidomainhost): http://msdn.microsoft.com/en-us/library/system.loaderoptimizationattribute.aspx
Mike Cheel
A: 

What you want is NGEN, which pre-compiles the assemblies for you. I think the problem you're going to have is that the assemblies from the network, and potentially being loaded for different CPU architectures. NGEN should be run on the destination computer as it compiles and optimizes for the specific architecture that computer uses.

What you might consider is giving the assemblies strong names and installing them into the GAC on each computer.

I don't think the approach you're considering is going to work, I think you're going to load them into the service process and once they're released they will be cleaned up by the system and the net result will be no speed increase.

Coding Gorilla
+1  A: 

You can pre-jit assemblies programmatically using the technique described in the following article: Pre-compile (pre-JIT) your assembly on the fly, or trigger JIT compilation ahead-of-time.

However I do not think jitting them in one process will have effect on another one (not sure about it). One possible solution is to start your application at computer with command line options indicating that it should only prejit assemblies and do nothing else. When the user launches the application it will tell the already running process to start its default functionality.

Giorgi
I like the idea... this would surely work if the loading happens in the same process as the actual work... Now to try and do it from different processes...
Pierre-Olivier Goulet
+1  A: 

You already know that JIT compiling is not the problem, that would also slow down the second start. All you have to do is get the DLLs in the file system cache. So that when you start the program later, it will use the copy of that DLL from the cache instead of digging through the network attached drive to find it. Which is what is taking time. Office Quick Start is using the same trick. Not sure who will win if all this preloaded stuff doesn't fit anymore.

Just create a Winforms app, so you don't get a window, and call Assembly.Load() to get the assemblies loaded, File.ReadAllBytes() to ensure the entire content is in the cache. Put a shortcut to this program in the Startup folder. That one assembly you mentioned is plenty big enough to get a boost in the warm start from Ngen.exe. That has to be run on each individual work station though.

Hans Passant