Reducing WinForm Memory Footprint with SetWorkingSet(reference)

Windows Forms apps are pretty bloated in terms of memory usage. The main reason .Net apps have such a huge footprint is that the JIT compiler loads when the app starts and all that bootstrap code and a ton of the WinForms engine is loaded and compiled at startup and gets loaded into your process. Beside the fact that this takes up processor cycles it also consumes a lot of memory. The JIT is pretty good about which code gets compiled – for the most part it compiles only code that actually gets run, but the framework itself pulls in a lot of code as well and that gets compiled as well. Third party controls - ditto. The result of this is that on startup your app consumes a lot of resources that you will not need any longer once the app is up and running. Actually if you access another new part of the application that part will compile later, but for many apps the startup and main application form make up a huge chunk of what gets loaded and compiled as the data engine and business objects etc. usually are among the things that get called at startup. A large percentage generally gets compiled right at startup.

If you’ve ever run your app and looked at Task Manager you might have noticed that the app starts out with a significant amount of memory. A basic WinForm app with a couple of textboxes and a button typically will run around 8 megs. If you move the form around a bit closer to 10. You then can minimize the app and it generally reduces to some really low memory usage number which slowly creeps back up as you open the form back up. What’s happening is that the app internally is adjusting the Working Set for the application which aggressively reduces the memory in use by the app. The app will reclaim what it needs, but for that moment the memory usage goes down drastically and it will stay much lower than the original startup usage.

For .Net applications this is a useful feature because there’s so much gunk that loads in .Net apps that goes away. You can force your app to minimize and pop back up to get the same effect, but this is probably not something that you want to do in your application <g>. A better way is to adjust the working set in your applications like this:

 

 1 public static void SetWorkingSet(int lnMaxSize,int  lnMinSize) 
 2 

 3 
 4 

 5 System.Diagnostics.Process loProcess =  System.Diagnostics.Process.GetCurrentProcess(); 
 6 

 7 loProcess.MaxWorkingSet =  (IntPtr) lnMaxSize; 
 8 

 9 loProcess.MinWorkingSet =  (IntPtr) lnMinSize; 
10 

11 //long lnValue = loProcess.WorkingSet; // see what the actual value 
12 
13 
14 

I’ve taken to calling this static method function in my code at the end of the Win form’s Load event and also in the Deactivate event. The latter is kind of cheating . If you go checking to task manager for memory usage you’re actually deactivating the app, and so you get a lower value.

 

1 private void frmWebStoreMain_Deactivate(object  sender, System.EventArgs e) 
2 

3 
4 

5 wwUIRoutines.SetWorkingSet(750000,300000 ); 
6 

7 
8 

 

The value will not actually reduce to exactly what you tell it to, but Windows will try to reduce as much as possible. Memory usage readings in TaskManager aren’t really all that accurate, but I’ve heard from several people using some of our tools that they really were surprised by the memory usage. Doing something like the above reduced memory usage considerably.

For example, Web Monitor without the above code runs around 14-15megs. With the above code (as part of the monitoring thread) the typical memory usage runs between 5-7 megs. For the Web Store Client app without the above the app runs 25 megs. With the code it runs at 7-10megs.

In a way this is cheating the app – but it certainly improves the impression of memory usage of the application on the machine. I suspect that this has little effect on actual performance as the memory would be reclaimable anyway if the system needed it. But given that some people look at program size as an indication of the bloat in an app it can’t hurt to do this.

Note that there is some overhead in doing this. You’re freeing causing memory to be freed from the app – memory that will have to be reclaimed later if it is needed again. So be careful with this sort of thing in high performance applications.

 

 

你可能感兴趣的:(reference)