您的位置:首页 > 编程语言 > C#

【转】有效减少WinForm程序的内存占用 C#

2009-12-18 15:31 393 查看
微软的 .NET FRAMEWORK 现在可谓如火如荼了。但是,.NET 一直所为人诟病的就是“胃口太大”,狂吃内存,虽然微软声称 GC
的功能和智能化都很高,但是内存的回收问题,一直存在困扰,尤其是 winform
程序,其主要原因是因为.NET程序在启动时,是需要由JIT动态编译并加载的,这个加载会把所有需要的资源都加载进来,很多资源是只有启动时才用的。






XP

系统为例子,程序启动后,打开任务管理器,会看到占用的内存量比较大,你把程序最小化,会发现该程序占用的内存迅速减小到一个很小的值,再恢复你的程序,你会发现内存占用又上升了,但是比你刚启动时的内存占用值还是小的,这就是一个资源优化的过程,这个过程是操作系统主动完成的。



上面的情况,在
vista


下并不是这样的,最小化后,内存占用量不会改变,说明vista对内存的管理比XP优秀(个人意见


)。



进程的工作集是物理 RAM 内存中当前对该进程可见的内存页的集合。这些内存页是常驻内存,

可供应用程序使用,而不会触发页面错误。

工作集包括共享数据和私有数据。共享数据包括那些包含应用程序执行的所有指令的页

(包括 .dll 文件和 system.dll 文件中的页)。随着工作集大小的增加,内存需求也增加。

进程具有最小和最大的工作集大小。每次创建进程资源时,系统都会保留等于该进程最小工作集

大小的内存量。虚拟内存管理器会尝试在进程处于活动状态时至少保留最小的常驻内存量,

但决不会保留超过最大大小的内存量。

系统设置默认工作集大小。可以使用 MaxWorkingSetMinWorkingSet
成员修改这些大小。

但是,设置这些值并不保证将保留或驻留该内存。



说明:

当您增加进程的工作集大小时,您就从系统的其余部分取走了物理内存。

确保不要请求太大的最小或最大工作集大小,因为这样做会降低系统性能。





下面给出我实测的一些数据:



测试用例:只有一个窗体的空白winform程序,.net frame 2.0




XP SP3 操作系统


启动后:



最小化后:



还原后:





通过上面三个图,大家可以很明白的看到 内存 的变化情况。

一个再简单不过的.net的winform程序,启动后都要占用7M左右的内存。

所以,作为一种投机取巧的办法: 在程序启动完成后,先最小化程序,再还原,也是一种节约资源的方法,嘿嘿




Vista SP1 32位 操作系统


启动后:



最小化后:



还原后:





有上面的三幅图,可以看到,在 vista 下, 内存基本没有变化。

而且在vista下的,同一个程序, 内存只占用了 2M 多一点, 比 XP 好了很多。





下面开始我们要说的 WorkingSet 的部分

.net 的 Process 有一个 WorkingSet64 的属性,表示当前进程所占用的物理内存值,是以字节为单位的。Process 还具有
MaxWorkingSet 和 MinWorkingSet 及相关的一些属性, 其中 MaxWorkingSet
的默认值是
1413120 字节,MinWorkingSet
的默认值是 204800 字节。

我们可以通过设置 进程的 MaxWorkingSet 的值,
来降低其内存使用量,但是这个值的设置,一定要合理,否则可能会适得其反。对于我们的上面的测试程序,只需要在 Form_Load 事件里,加入一句:

System.Diagnostics.Process.GetCurrentProcess().MaxWorkingSet = (IntPtr)750000;


大家就可以看到效果了, 但是还有个问题, 经过这次设置后, 随着程序的运行,它所占用的内存会逐步回升, 所以, 我们需要定时去设置一下进程的
MaxWorkingSet 值, 这个工作, 交给一个 timer 就OK了。


具体步骤:

通过设置当前进程的MaxWorkingSet值来调整程序的内存占用:

public static void SetWorkingSet(int maxWorkingSet)

{

System.Diagnostics.Process.GetCurrentProcess().MaxWorkingSet

= (IntPtr)maxWorkingSet;

}

定义一个maxWorkingSet值:

int maxWorkingSet = 750000;

在窗体加载和窗体被停用时调用此静态方法:

private void Form1_Load(object sender, EventArgs e)

{

Working.SetWorkingSet(maxWorkingSet);

}

private void Form1_Deactivate(object sender, EventArgs e)

{

Working.SetWorkingSet(maxWorkingSet);

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: