SetProcessWorkingSetSize 降低程序运行内存

在项目中对程序性能优化时,发现用SetProcessWorkingSetSize()
方法使内存降低了很多,于是查阅了相关的资料如下。

一 SetProcessWorkingSetSize 的工作原理

以下来自:http://blog.csdn.net/zlt982001/archive/2005/08/28/466879.aspx

那么我的程序为什么能够将占用的内存移至虚拟内存呢?

其实,你也可以,试试看把一个程序最小化到任务栏,再看看任务管理器,看到没,你的程序占用的实际内存一下子减少了,看来并不是我有什么方法能够压缩内存,而是操作系统本身就有这个机制,即当程序不使用时(最小化),操作系统会调用某些命令,来将该程序占用的内存移至虚拟内存,只保留一小部分常规代码

所以我们就看到了 这种情景,占用的内存一下子就缩小了。

那么:系统到底调用了什么指令呢?能不能在不缩小窗体的情况下来释放内存呢?

看看这个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,请放在适当的地方

二 区分物理内存、虚拟内存、Working Set(Memory)、Memory

以下来自:http://blog.joycode.com/qqchen/archive/2004/03/17/16434.aspx

这个问题在CSDN上碰到好几次,我每次都只给出了简单的答案:不要参考Task Manager的Mem
Usage数据,那个数据的大小对程序性能没有直接影响。
下面是我分析这问题的一些思路,希望对对这个问题感兴趣的朋友有所帮助

Q: Is .NET Alone?
A: Nope!
前面Saucer说过了,这不是.NET的问题,所有Windows程序都有类似的行为。例如下面的C程序:
void main { while(1);
}   //死循环,便于我们察看Task Manager
初次运行在我的机器上Mem
Usage是632K,把Console最小化以后再恢复,Mem Usage变成了36K。显然,这不是一个.NET独有的问题,而是Windows Memory
Management的问题。那么和.NET的GC机制也不会有太大的关系——虽然问题的表现形式很容易让人联想到GC。

Q: How much memory does my program
use?
A: 回答这个问题并不容易。先来看看操作系统虚拟内存管理的一些基本概念:每个Windows进程都拥有4G的地址空间,但是你的机器显然没有4G的物理内存。在多任务环境下,所有进程使用的内存总和可以超过计算机的物理内存。在特定的情况下,进程的一部分可能会从物理内存中删除而被暂存在硬盘的文件里(pagefile),当进程试图访问这些被交换到pagefile里的内存的时候,系统会产生一个缺页中断(page
fault),这时候Windows内存管理器会负责把对应的内存页重新从硬盘调入物理内存。
在某个时间内,一个进程可以直接访问到的物理内存(不发生缺页中断)叫做这个进程的Working
Set;而一个进程从4G的地址空间当中实际分配(commit)了的、可访问的内存称为Committed Virtual Memory。Committed
VM可能存在于Page File当中,WorkingSet则一定位于物理内存。
所以要回答上面的问题先要反问一句:What‘re you talking
about? Physical Memory or Committed Memory?

Q: What is this "Mem Usage"
data?

A: From Task Manager Help: In Task
Manager, the current Working Set of a process, in kilobytes. 
Mem
Usage这个名字多少有些误导。它只表示这个进程当前占用的物理内存,也就是WorkingSet。WorkingSet不表示进程当前“占用”的所有虚拟内存,该进程可能还有一部分数据被交换到pagefile当中。这些数据只有在被访问的时候才会被加载到物理内存。
Task
Manager有另一列数据:VM Size,表示了一个进程分配的虚存(Committed Visual
Memory)——实际的定义要比这个复杂一些,但这个定义对我们目前分析的问题已经足够了。以前面的C程序为例,在最小化前后的VM
Size都是176K,并没有变化。
所以,结论很简单:当一个Windows程序被最小化的时候,Windows内存管理器把该进程的WorkingSet减到最小(根据先进先出FIFO或者最近最少使用LRU),把大部分数据交换到pagefile里。这很容易理解:我们通常总是希望为前台的应用程序留出更多物理内存,从而具有更好的性能。当该程序从最小化恢复的时候,Windows也不会完全加载程序的所有虚存,只是加载了必要的部分。这也很容易理解:程序启动阶段的代码通常在启动之后很少访问(对.NET程序尤其如此,向fusion这样的模块在程序正常加载之后如果没有用到Reflection通常用不到)。

Q: So, Do we want a smaller workingset, or a larger
one?

A: It depends. Conventional Wisdom tells
us: The smaller, the better.
但是在虚存的问题上却没这么简单。如果WorkingSet太小,程序运行过程中会产生很多缺页中断,这会严重影响程序的性能。另一方面,WorkingSet太大会浪费“宝贵的”物理内存,降低整个系统的性能。
通常情况下(除非是对性能非常敏感的应用程序,并且你对Windows的内存管理了如指掌),建议不要在程序中自己调整WorkingSet的大小,而把这个任务交给Windows内存管理器。调整的方法Saucer有提到: SetProcessWorkingSetSize();

Q: Final Question, Does my program really occupy that much physical
memory?

A: 这个问题看上去土了点——那个数字明明白白的写在Task
Manager里面。
sam1111用vadump检查的结果显示进程WorkingSet减小的主要原因是很多DLL在从最小化恢复的时候没有被加载到物理内存。我们知道DLL的一个特点是代码共享,以NTDLL.DLL为例,整个Windows系统的几乎所有应用程序(具体地说,Win32子系统的所有程序)都需要引用NTDLL.DLL,如果每人一份,光这个文件就的占用几十兆内存。Windows地解决办法是只在物理内存中保存一份NTDLL.DLL的COPY,所有引用这个DLL的程序都把这一份COPY映射到自己的内存空间里面,共享NTDLL.DLL的代码段(每个进程的数据段仍然是独立的)。所以虽然NTDLL.DLL的大小被计算在你的程序的WorkingSet里面,但是从你的程序中去掉对这个DLL的引用并不会真的释放多少物理内存——你不用,别人还在用呢!
所以,你的程序“独占”的物理内存远没有Mem
Usage所表示的那么多,需要从Mem Usage里面扣除很多Shared Code Page (vadump里面可以看到)。

结论?不要参考Task Manager的Mem Usage数据,那个数据的大小对程序性能没有直接影响。用Perfomence
Monitor里面与.NET相关的Counter要容易、准确的多。

SetProcessWorkingSetSize 降低程序运行内存,码迷,mamicode.com

时间: 2024-11-25 06:45:40

SetProcessWorkingSetSize 降低程序运行内存的相关文章

【转载】EmptyWorkingSet 程序运行内存整清理

网络上找了很多关于内存整理的文章,不外乎都是使用EmptyWorkingSet来实现.就如下面这段代码. #include "stdafx.h"#include <windows.h>#include <tlhelp32.h>#include <psapi.h>#pragma comment (lib,"psapi.lib") BOOL EmptyAllSet(){    HANDLE SnapShot=CreateToolhel

PHP 中巧用数组降低程序的时间复杂度

PHP 中巧用数组降低程序的时间复杂度 通常开发人员在写程序的时候,往往是把已经设计好或者构思好的运算逻辑,直接用编程语言翻译出来.程序能顺利编译通过,那是很令人高兴的事情.如果此时程序的运行时间还能接受,就会沉浸在写代码的成就感当中,常常在这个过程中忽略代码的优化.只有当程序运行速度受到影响时,才回过头去考虑优化的事情. 本文主要是介绍在 PHP 的编程中,如何巧用数组来降低因多层循环而引起的时间复杂度的问题.特别是当程序需要多次与数据库交互时,用此方法来优化你的代码,将会带给意想不到的效果.

关于程序猿怎样降低程序Bug的若干建议

毫无疑问,程序猿是善于思考问题的一族. 一个程序的编写都是通过:思考.设计.编写.调试.測试以及执行这些主要的阶段. 但大部分程序猿都有一个问题就是不太愿意測试自己的代码. 他们草草的调式完毕以后就觉得工作结束,測试那是測试人员的工作. 依照理论上.假设代码存在问题.那么測试人员和终于的用户肯定能够发现这些 BUG ,而等待哪个时候再返回来查找问题究竟错在什么地方确实代价不小,其代价有: 1. 影响了程序猿自己的声誉 2. 影响了产品的质量 3. 影响了客户的信任度 4. 这个时候再 DEBUG

谈程序的腐化

写代码如同打扫屋子,有句话叫一屋不扫何以扫天下.如果单个的一个模块代码都不能管好,如何成就一个完善的软件系统? 写代码如同打扫屋子,有句话叫一屋不扫何以扫天下.如果单个的一个模块代码都不能管好,如何成就一个完善的软件系统? 今天我们来说说,一个代码模块的代码是如何一步步腐化变质,到最后程序员都不愿意去维护它,然后要么重构,要么废弃换新模块的? 代码是有一定的周期的,这个没有错.为什么有的代码跑上几十年仍然好用,而现在互联网公司的很多代码,每年都要做好几次重构?一个成立2年的互联网公司,做一个支付

毁掉程序员的十个恶习

作为一个敢于追求潮流的人,并励志做到专业的帅哥,在学习前端的这段时间里发现了自己很 多的弯路,下面分享一下(供大神拍砖). 从学习web前端开始的1个半月的时间里,自己从一名刚开始的网络方面思考方式转到软件开发 人员敏捷的程序思考方式.成为一名软件开发人员不是那么的容易,尤其是自己在大学期间把 所有的精力都用在了网络方面,所以现在自己的软件方面的知识很少,思维也不够的灵活,但 这是缺点同时也是优点,大学教会了自己养成认真的习惯,努力肯学,同时也培养了自己的思 考能力,但我知道这些思考能力是远远不

Unix下C程序内存泄露检测工具:valgrind的安装使用

Valgrind是一款用于内存调试.内存泄漏检测以及性能分析的软件开发工具. Valgrind的最初作者是Julian Seward,他于2006年由于在开发Valgrind上的工作获得了第二届Google-O'Reilly开源代码奖. Valgrind遵守GNU通用公共许可证条款,是一款自由软件. Valgrind的安装和使用 去官网www.valgrind.org下载最新版本的valgrind,我这里下载的是valgrind 3.11.0.tar.bz2. #tar xvf valgrind

黑马程序员-Java多线程操作

--Java培训.Android培训.iOS培训..Net培训.期待与您交流!--- Java中的线程 一个程序的运行需要启动一个应用进程,一个进程可以创建多个线程,帮助应用完成多任务操作,实现并发运行.在Java中线程是被封装成Thread类,进行多线程操作时只需要继承一个Thread类,实现自己的功能即可,然后开启此线程,或者你也可以实现一个Runnable接口,然后将其传递给Thread对象,然后再启动它. 线程的创建于启动 继承Thread 创建一个类并继承Thread类,然后实现Thr

一个无锁消息队列引发的血案:怎样做一个真正的程序员?(二)——月:自旋锁

前续 一个无锁消息队列引发的血案:怎样做一个真正的程序员?(一)——地:起因 一个无锁消息队列引发的血案:怎样做一个真正的程序员?(二)——月:自旋锁 平行时空 在复制好上面那一行我就先停下来了,算是先占了个位置,虽然我知道大概要怎么写,不过感觉还是很乱. 我突然想到,既然那么纠结,那么混乱,那么不知所措,我们不如换个视角.记得高中时看过的为数不多的长篇小说<穆斯林的葬礼>,作者是:霍达(女),故事描写了两个发生在不同时代.有着不同的内容却又交错扭结的爱情悲剧,一个是“玉”的故事,一个是“月”

应用 Valgrind 发现 Linux 程序的内存问题

如何定位应用程序开发中的内存问题,一直是 inux 应用程序开发中的瓶颈所在.有一款非常优秀的 linux 下开源的内存问题检测工具:valgrind,能够极大的帮助你解决上述问题.掌握 valgrind 的使用以及工作原理,能够有效地定位进而避免应用开发中的内存问题. 5 评论: 杨 经 ([email protected]), 软件工程师, IBM 2008 年 11 月 27 日 内容 应用 Valgrind 发现 Linux 程序的内存问题 回页首 Valgrind 概述 体系结构 Va