关于 SetProcessWorkingSetSize 和内存释放
在应用程序中,往往为了释放内存等,使用一些函数,其实,对于内存操作函数要谨慎使用,比如大家常常想到的
SetProcessWorkingSetSize,其实对于windows来说,系统会自动在程序闲置时(如程序被最小化)释放内存的,自己用内存释放
时,往往会造成一些莫名的内存错误,造成自己的应用程序及系统不稳定。
具体原理有人已经写得很清楚了,以下为转帖的几个帖子,供参考:
=============================================
1、将物理内存的占用挪到虚拟内存里-----揭密篇
将物理内存的占用挪到虚拟内存里-----揭密篇
参见 VB(或任意程序)将物理内存的占用挪到虚拟内存里
那么我的程序为什么能够将占用的内存移至虚拟内存呢?
其
实,你也可以,试试看把一个程序最小化到任务栏,再看看任务管理器,看到没,你的程序占用的实际内存一下子减少了,看来并不是我有什么方法能够压缩内存,
而是操作系统本身就有这个机制,即当程序不使用时(最小化),操作系统会调用某些命令,来将该程序占用的内存移至虚拟内存,只保留一小部分常规代码
所以我们就看到了 这种情景,占用的内存一下子就缩小了。
那么:系统到底调用了什么指令呢?能不能在不缩小窗体的情况下来释放内存呢?
看看这个API SetProcessWorkingSetSize
这是从MSDN摘下的原话
Using
the SetProcessWorkingSetSize function to set an application's minimum
and maximum working set sizes does not guarantee that the requested
memory will be reserved, or that it will remain resident at all times.
When the application is idle, or a low-memory situation causes a demand
for memory, the operating system can reduce the application's working
set. An application can use the VirtualLock function to lock ranges of
the application's virtual address space in memory; however, that can
potentially degrade the performance of the system.
使用这个函数来设置应用程序最小和最大的运行空间,只会保留需要的内存。当应用程序被闲置或系统内存太低时,操作系统会自动调用这个机制来设置应用程序的内存。应用程序也可以使用 VirtualLock 来锁住一定范围的内存不被系统释放。
When
you increase the working set size of an application, you are taking
away physical memory from the rest of the system. This can degrade the
performance of other applications and the system as a whole. It can also
lead to failures of operations that require physical memory to be
present; for example, creating processes, threads, and kernel pool.
Thus, you must use the SetProcessWorkingSetSize function carefully. You
must always consider the performance of the whole system when you are
designing an application.
当你加大运行空间给应用程序,你能够得到的物理内存取决于系统,这会造成其他应用程序降低性能或系统总体降低性能,这也可能导致请求物理内存的操作失败,例如:建立 进程,线程,内核池,就必须小心的使用该函数。
========================
事实上,使用该函数并不能提高什么性能,也不会真的节省内存。
因为他只是暂时的将应用程序占用的内存移至虚拟内存,一旦,应用程序被激活或者有操作请求时,这些内存又会被重新占用。如果你强制使用该方法来 设置程序占用的内存,那么可能在一定程度上反而会降低系统性能,因为系统需要频繁的进行内存和硬盘间的页面交换。
BOOL SetProcessWorkingSetSize(
HANDLE hProcess,
SIZE_T dwMinimumWorkingSetSize,
SIZE_T dwMaximumWorkingSetSize
);
将 2个 SIZE_T 参数设置为 -1 ,即可以使进程使用的内存交换到虚拟内存,只保留一小部分代码
而桌面日历秀 之所以能够 总是保持 最小内存,是因为使用了定时器,不停的进行该操作,,所以性能可想而知,虽然换来了小内存的假象,对系统来说确实灾难。
当然,该函数也并非无一是处,
1 。当我们的应用程序刚刚加载完成时,可以使用该操作一次,来将加载过程不需要的代码放到虚拟内存,这样,程序加载完毕后,保持较大的可用内存。VB尤甚
2.程序运行到一定时间后或程序将要被闲置时,可以使用该命令来交换占用的内存到虚拟内存。
最后,附上VB 调用的API 代码
Option Explicit
Private
Declare Function SetProcessWorkingSetSize Lib "kernel32" (ByVal
hProcess As Long, ByVal dwMinimumWorkingSetSize As Long, ByVal
dwMaximumWorkingSetSize As Long) As Long
Private Declare Function GetCurrentProcess Lib "kernel32" () As Long
SetProcessWorkingSetSize GetCurrentProcess, -1, -1
将当前进程使用的内存归0,请放在适当的地方。
2、.net中内存占用的问题
今天开始解决系统占用内存过大的问题。
在
去年做系统的时候,就发现系统占用内存大,到今年6月,系统启动后占用内存达到60M,运行一段时间后达到100M左右(任务管理器监视的结果),到时想
各种办法都没有解决(包括GC.Collect、析构函数等),后来和灵感之源在MSN上讨论了一下,他认为可能是系统中使用MagicLibrary的
问题,因此也就搁置下来。
刚才在网上查到博客堂上也有人进行过讨论,知秋一叶作了精彩的解释,看了之后有茅塞顿开之感。在系统中使用
SetProcessWorkingSetSize方法做了一个测试,调用该方法后,占用内存从80M降到2M.(TaskManager观察的结果)按
照知秋一叶的说法,这样调整WorkingSet,将有可能导致缺页中断,严重影响性能。
但是从使用的情况来看,没有发现这样的现象,这可能是我使用这 个方法的原因:
public static int MinOf(uint pID)
{
IntPtr hd = OpenProcess((uint)PROCESS_ACCESS_RIGHTS.PROCESS_SET_QUOTA, false, pID);
try
{
if (hd != IntPtr.Zero && System.Environment.OSVersion.Platform == System.PlatformID.Win32NT)
{
return SetProcessWorkingSetSize(hd, -1, -1);
}
else
{
return -1;
}
}
finally
{
CloseHandle(hd);
}
}
以上代码来自 http://www.zpcity.com/ArLi//commonprj/cls_MinWorkSize.cs
依照知秋一叶的观点,系统采用这种方式来调整WorkingSet没有多大意义,但是看着taskmanager中的数字,确实不是很爽
该文的一些评论:
//多测试几次后发现,使用SetProcessWorkingSetSize方法确实可能造成系统不稳定。
//.net的gc还是值得信赖的,只要代码规范就行
//
你要这么看才知道有没有用处,否则频繁的page swap效率更低。