How to preload .net assemblies
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 fas开发者_开发技巧ter.
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 ...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.
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.
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.
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
精彩评论