关于 SetProcessWorkingSetSize 和内存释放

摘要:
应谨慎使用记忆操作功能。当程序空闲时(例如,程序最小化),系统将自动释放内存。当应用程序空闲或系统内存过低时,操作系统将自动调用此机制来设置应用程序的内存。应用程序还可以使用VirtualLock来锁定系统释放的特定范围的内存。这也可能导致请求物理内存的操作失败。如果强制使用此方法设置程序占用的内存,则系统需要频繁地在内存和硬盘之间交换页面。

在应用程序中,往往为了释放内存等,使用一些函数,其实,对于内存操作函数要谨慎使用,比如大家常常想到的 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还是值得信赖的,只要代码规范就行
//关于 SetProcessWorkingSetSize 和内存释放第1张
你要这么看才知道有没有用处,否则频繁的page swap效率更低。

免责声明:文章转载自《关于 SetProcessWorkingSetSize 和内存释放》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇库、教程、论文实现,这是一份超全的PyTorch资源列表(Github 2.2K星)创建 Java 项目下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Unity事件处理机制与NGUI事件机制

1 Unity原生 1.1 GUI void OnGUI(){ if(GUI.Button(Rect position, string text)){ //点击后立即执行 } 1.1 Input 每个手指触控是通过Input.touches数据结构描述的: fingerId 手指索引 The unique index for a touch. ...

公用技术——数据格式——JSON——Jackson类库——序列化——属性,键映射关系

  通常情况下,对象的属性与JSON键的关系是一对一,键的顺序是根据属性的顺序,键的名称是与属性的名称保持一致的。 Jackson有很多注解可以修改以上三种关系。首先从属性名称与键名称开始。 1、名称 1.1     @JsonProperty 在属性上添加@JsonProperty注解,给value赋值可以修改对应的键名称,例如User对象存在name属...

lua中文教程【高级知识】

一、编译和运行和调试 1、lua和其他解释型语言一样,先转换成为中间码再执行 2、dofile和loadfile的区别:loadfile编译返回不执行,返回错误代码;dofile执行,返回错误信息 3、loadstring通常用于程序外部的代码,load表达式,在前边加上“return”,assert方法发出警告信息 4、require方法:加载运行库【可...

linux文件系统

一、什么是文件系统 操作系统中用于管理和组织磁盘设备上文件的方法和数据结构叫做文件系统. 1.1 根文件系统(rootfs): 在Linux中, 文件系统和倒树形结构一样, 位于最顶层的的一个分区我们称之为根(root), 用于安装linux系统, 类似于Windos的系统盘; 根分区又叫做根文件系统(root filesystem). 根文件系统由内核...

c语言的几个重要知识点

目录: 1. 内存结构 2 .指针 3. 字符串处理 4. 裢表 5. 复习大纲中的一些知识点理解   1、 内存结构 这是核心中的核心,请仔细看完,充分理解,否则请不要看下一节内容。 每个程序一启动都有一个大小为4GB的内存,这个内存叫虚拟内存,是概念上的,真正能用到的,只是很小一部分,一般也就是在几百K到几百M。我们PC中内存,我们称之为物理内存,也...

DEP(数据执行保护)介绍

DEP - 数据执行保护的缩写,Data Execution Prevention。 数据执行保护 (DEP) 是一套软硬件技术,能够在内存上执行额外检查以帮助防止在系统上运行恶意代码。在 Microsoft Windows XP Service Pack 2、 Microsoft Windows Server 2003 Service Pack 1...