Tzot

We must accept finite disappointment, but we must never lose infinite hope. -- Mattin Luther King
  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理

公告

2008年8月28日

第一次翻译文章,错误在所难免。让大家见笑了!还希望高手多指点。。

 

   Windows Form应用程序在内存使用方面显得非常臃肿。主要是因为.NET应用程序在启动的时候有大量的footprintJIT编译器加载,并且所有的链代码和WinForms引擎在启动时候被编译,并加载到程序的进程。这一过程占用了处理器时间片的同时也占用了大量的内存。JIT在确定哪些代码应该被编译已经做的非常好了,大部分其编译的代码都是事实上要用的。但是.NET框架本身也会要求编译一些代码。这样的结果就是程序进程加载了很多只在启动的时候才会用的资源。

   如果你已经运行了你的程序,那在任务管理中你会发现其占用了很大的内存。基本上一个由TextBoxButton组成的典型WinForm程序要占用8M的内存。If you move the form around a bit closer to 10。(不知道这个怎么翻,:)你可以最小化窗口,那内存使用就会降下来,如果再重新打开,那内存又会慢慢提升。这个现象是因为程序内部调整了工作集的大小从而释放了一些资源。如果程序发现其需要部分不再内存中,那将会再次将该部分加载到内存中,但是内存占用还是会比一开始启动时候低很多。

对于.Net应用程序而言,这是一个非常有用的功能,因为大量启动过程中载入的资源被清掉。你可以强迫你的程序最小化再恢复窗口到原来状态来达到这个释放资源的效果,但是这个方法可能不是你在自己应用程序中希望看到的。那更好的方法就是在你的程序中调整工作集大小:

 

 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 

 

我已经在WinForm Load事件以及Deactivate事件中调用了这个静态方法。后者是一种欺骗行为。如果你再去到任务管理器中去查看内存使用那个情况,你就会发现内存使用量非常低。

 

1 private void frmWebStoreMain_Deactivate(object sender, System.EventArgs e)
2 
3 {
4 
5       wwUIRoutines.SetWorkingSet(750000,300000);
6 
7 }
8 

 

    工作集的大小并不一定会减少到你设置的那个值,但Windows会尝试以尽可能减少。事实上在任务管理器中看到的内存使用也不是精确的,但我听说有些人用了这些方法后,减少了非常到内存使用量,他们对此感到惊讶不已。

    比如说,网络监控程序无上述代码运行约14 - 15megs的内存。在应用了上述代码后(作为监控线程的一部分)内存使用量5-7 megs之间。网上商店用户端应用程序,没有使用上述代码,程序运行需要25 megs内存。使用上述代码后程序运行在7 10megs

    从某种意义上讲,这是在欺骗应用程序—-但是这个的确能提高程序在这台机器中内存使用的印象。我认为,这个对实际性能(PC)影响不大,因为如果系统需要,内存无论如何都会被回收。但是对于那些以内存为衡量标准的人而言,这样做还是很有意义的。

    请注意,这个行为是有一定开销的,也就说会影响性能。因为在释放了资源后,内存也被回收,但是如果程序再次需要这个资源时,那该部分将再次被加载到内存中,那这个过程就会对性能有一定的影响。因此要小心使用这个方法在需要高性能的程序中。

 

原文地址:http://www.west-wind.com/Weblog/posts/240.aspx

posted @ 2008-08-28 16:27 Tzot 阅读(816) 评论(1) 编辑

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.

 

 

posted @ 2008-08-28 14:34 Tzot 阅读(285) 评论(1) 编辑