SetProcessWorkingSetSize 函数的骗局

SetProcessWorkingSetSize函数的骗局

本文引用自:http://hi.baidu.com/jenson138/item/e64e7e453c5b28e21381da9c

我实在不愿意提起这个话题.后来在网上看到几篇文章,深深感觉到,已经有程序员站出来,揭穿这个忽悠了千百万用户的诡计了...
附2篇文章的地址:
http://blog.csdn.net/biku/archive/2006/07/06/886038.aspx
http://blog.csdn.net/zlt982001/archive/2005/08/28/466879.aspx
我这篇文章无非是归纳了几篇文章的内容,并深入的阐明恶意使用该技术带来的坏处.
请一味追求低内存软件的用户们注意了:什么才应该是选择软件的主要因素.

物理内存和虚拟内存

物理内存,在应用中,自然是顾名思义,物理上,真实的插在板子上的内存是多大就是多大了.看机器配置的时候,看的就是这个物理内存.

如果执行的程序很大或很多,就会导致物理内存消耗殆尽.为了解决这个问题,Windows中运用了虚拟内存技术,即拿出一部分硬盘空间来充当内存使用,当内存占用完时,电脑就会自动调用硬盘来充当内存,以缓解内存的紧张.

一个程序,不可避免地要用到虚拟内存,因为不频繁执行或者已经很久没有执行的代码,没有必要留在物理内存中,只会造成浪费;放在虚拟内存中,等执行这部分代码的时候,再调出来.
Windows 的任务管理器可以帮助我们看到进程的虚拟内存.调出任务管理器,点击菜单“查看”-“选择列”,在出现的窗口中,钩上“虚拟内存大小

一个程序到底应该使用多少虚拟内存呢?不一定,但是应该以恰到好处的符合虚拟内存原本作用为最好.
下面将揭穿表面看起来调用了大量图片、大量运行库的程序,为什么才“占用”不到 1 MB 的内存的诡计.

原来是 SetProcessWorkingSetSize 函数

MSDN 对该函数的表述(翻译):使用这个函数来设置应用程序最小和最大的运行空间,只会保留需要的内存.当应用程序被闲置或系统内存太低时,操作系统会自动调用这个机制来设置应用程序的内存.应用程序也可以使用 VirtualLock 来锁住一定范围的内存不被系统释放;当你加大运行空间给应用程序,你能够得到的物理内存取决于系统,这会造成其他应用程序降低性能或系统总体降低性能,这也可能导致请求物理内存的操作失败,例如:建立 进程,线程,内核池,就必须小心的使用该函数.

也就是说,该函数不是节省内存,而是强制把进程的物理内存搬到虚拟内存中.

另外有一些资料上说,该函数“将有可能导致缺页中断,严重影响性能”.
函数原型:
BOOL SetProcessWorkingSetSize(
HANDLE hProcess,
SIZE_T dwMinimumWorkingSetSize,
SIZE_T dwMaximumWorkingSetSize
);
我们用 VB 来做这么一个简单的例子,是程序占用 300 KB 内存吧.

建立一个标准的 VB 工程,在 Form1 中放置一个 Timer1 ,把 Interval 属性设置为 1000 (即 1 秒).然后在代码编辑框中输入以下代码:

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
Private Sub Timer1_Timer()
SetProcessWorkingSetSize GetCurrentProcess(), 50000, 100000
End Sub
然后生成 工程1.exe,执行,调出任务管理器查看,发现内存占用才 320 KB.如果把定时器关闭,这进程的内存一般 4 MB左右.
必须定时执行该函数,否则虚拟内存会慢慢被调出来,恢复原来的内存大小.
如果要使一个本来需要占用大量内存的程序减低到几百 KB ,使用同样的方法即可.

诡计带来的危害

如果 SetProcessWorkingSetSize 函数被正常使用,是非常有用处的.但是为了蒙骗用户的眼睛,每秒,甚至几十毫秒就把大量内存往虚拟内存里面压,就会带来无可预计的危害.看看这篇文章怎么 说:“因为他只是暂时的将应用程序占用的内存移至虚拟内存,一旦,应用程序被激活或者有操作请求时,这些内存又会被重新占用.如果你强制使用该方法来设置 程序占用的内存,那么可能在一定程度上反而会降低系统性能,因为系统需要频繁的进行内存和硬盘间的页面交换.”.

没错,如果你使用了这类软件,意味着你的硬盘将每秒将 I/O 大量数据;硬盘的磁针将拼命旋转...(当然硬盘磁针不可能不旋转^_^,只是选择得更厉害而已).

不是说 BT 很伤内存吗?不然,因为现在大多 BT 软件都有缓存技术.且看 Bitcomet 官方对缓存技术的说明:“传统BT高速下载时硬盘会响得很厉害,这是大量的随机读取造成的.... BitComet可以由用户设置缓存大小.... 可以明显地看出牺牲一小部分内存作缓存对硬盘的保护作用.”

是不是有种心寒的感觉?一类软件宁愿牺牲内存,也要减少保护硬盘;而另外一类软件,却为了欺骗用户,让CPU、硬盘更加奔波......

抓一个凶手

这类软件不少,我以其中一个桌面工具为例,揭穿它的假面具(不点名字了).运行该软件后,随意操作一下,然后打开进程管理器,把虚拟内存列调出来,找到该进程,如图3:

OK,20 MB 虚拟内存,而只有 632 KB 物理内存.细心的你会发现,大概每 1 秒,该行都有闪烁的感觉,没错,这正是每秒调用 SetProcessWorkingSetSize 的结果.另外,我们打开 Norton Process Viewer ,查看该进程的 CPU 占用情况,如图4:

可以看到,就算没有操作该软件,但是每秒,都有 3% 的CPU占用起伏(虽然这并不能说明什么).另外,内存框中可以看到物理内存和虚拟内存的占用,两者相去甚远.此外,可以用 Hook API 技术来证明每秒调用 SetProcessWorkingSetSize 的行为.

应该怎么做

这篇文章只想让用户了解软件占用资源的实际.而程序员应该把下功夫,真正从代码中减少内存的消耗,而不是一味忽悠用户.调用 SetProcessWorkingSetSize

会带来某些好处,但是何时调用、如何调用应该符合两个要求:
1,在程序暂时不被使用的时候(例如最小化);
2,物理内存和虚拟内存应处于一个合适的比例(而不是 600 KB 比 20 MB 这么荒唐);
3,或者不调用,让 Windows 去处理.

转载于:https://www.cnblogs.com/fwycmengsoft/archive/2013/05/28/3103794.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/261628.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

iframe实现页面无刷新上传文件(PHP)----备忘

之前做一个文件上传的,由于那段时间写ajax比较多,所以就想利用Ajax来实现,后来发现,Ajax没法实现文件上传, 后来百度之,这里做个备忘。 提示:利用form表单的target属性和iframe 一、上传文件的一…

native react 常用指令_React Native入门基础篇(一)

学习一次,随处书写。(以下文字来自各大网上资料整理而来,侵删!)概述使用React为Android和iOS创建本机应用React Native将本机开发的最佳部分与React(用于构建用户界面的一流JavaScript库)结合在一起。 少用或多用。您现在可以在现有的Android…

C语言交换两个数(不创建临时变量)

方法一.加减法 #define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> int main() {int a 10;int b 20;//加减法a a b;b a - b;//b原来的aa a - b;//a原来的b//缺点&#xff1a;若a、b为较大的数会溢出printf("%d %d", a, b);return 0; }二.异或法 #de…

zoj 3511 Cake Robbery(线段树)

题目链接&#xff1a;zoj 3511 Cake Robbery 题目大意&#xff1a;就是有一个N边形的蛋糕。切M刀&#xff0c;从中挑选一块边数最多的。保证没有两条边重叠。 解题思路&#xff1a;有多少个顶点即为有多少条边&#xff0c;所以直接依照切刀切掉点的个数排序&#xff0c;然后用线…

在Android命令行启动程序的方法

在Android中&#xff0c;除了从界面上启动程序之外&#xff0c;还可以从命令行启动程序&#xff0c;使用的是命令行工具am.启动的方法为 # am start -n 包(package)名/包名.活动(activity)名称 启动的方法可以从每个应用的AndroidManifest.xml的文件中得到&#xff0c;以计算器…

IIS 6.0支持.SHTML

许多网站为了做seo优化&#xff0c;都把页面做成静态页面&#xff0c;方便搜索引擎的抓取&#xff0c;许多静态页面都是做成shtl页面的&#xff0c;这样做的好处是shtml页面可以包含html和htm文件&#xff01; 下面讲解下iis配置方法&#xff0c;让iis支持shtml页面方法如下&am…

python每隔半个小时执行一次_一篇文章教你用Python抓取微博评论

【Part1——理论篇】试想一个问题&#xff0c;如果我们要抓取某个微博大V微博的评论数据&#xff0c;应该怎么实现呢&#xff1f;最简单的做法就是找到微博评论数据接口&#xff0c;然后通过改变参数来获取最新数据并保存。首先从微博api寻找抓取评论的接口&#xff0c;如下图所…

eclipse导入class文件

右键src文件夹-》build path-》config build path-》library-》add class folder-》create new folder&#xff0c;此时在工程中会出现Referenced Librarier,在其中包含了你的新文件夹&#xff0c;同时在其下面出现了你的新文件夹&#xff0c;这时右键你的新文件夹-》import-》…

统计一个数的补码中二进制中1的个数

方法一&#xff1a; #include<stdio.h>int count_one_bit(int n){int count 0;while (n){if (n % 2 1){count;}n n / 2;}return count; } int main() {int num 0;int count 0;scanf("%d", &num);countcount_one_bit(num);printf("%d\n", c…

Oracle 随机获取N条数据

Oracle 随机获取N条数据 当我们获取数据时,可能会有这样的需求,即每次从表中获取数据时,是随机获取一定的记录,而不是每次都获取一样的数据,这时我们可以采取Oracle内部一些函数,来达到这样的目的1) select * from (select * from tablename order by sys_guid()) where row…

优先级队列,代码参考范例

一个看起来比较规范的代码&#xff1a; 1、版本信息 2、预处理信息 3、库函数引用 4、泛型编程 5、宏定义 6、复制构造函数 7、内敛函数 8、变量命名规范 9、代码的时间空间效率 10、错误恢复能力 11、规范的注释和缩进 代码范例&#xff1a; /*******************************…

r数据框计算字符出现次数_R语言系列第二期:①R变量、脚本、作图等模块介绍...

在上一篇文章里&#xff0c;给大家介绍了R语言的下载&#xff0c;界面操作&#xff0c;6个处理对象等等。在这些内容的基础上&#xff0c;我们在这个部分为大家介绍一些实用知识&#xff0c;包括描述工作区结构、图形设备以及它们的参数等问题&#xff0c;还有初级编程和数据输…

$.AjaxFileUpload is not a function

2019独角兽企业重金招聘Python工程师标准>>> ..is not a function错误的可能情况&#xff1a; 1、JS引入的路径不对。检查方法是看浏览器控制台是否将JS载入了进来。 2、JS引入顺序不对。JS要在你使用之前引入 3、Jquery没有第一个引入。 4、函数所在script标签&…

打印一个整数二进制表示中所有的奇数位和偶数位

#include<stdio.h>void my_print(int n){int i 0;printf(" 打印奇数位\n");for (i 30; i >0; i i - 2){printf("%d ", (n >> i)&1);}printf("\n");printf("打印偶数位\n");for (i 31; i >1; i i - 2){prin…

60个数据窗口技巧(转)

60个数据窗口技巧 1.如何让存储文件目录的列&#xff0c;显示图片? 答&#xff1a;选择对应的column的display as picture属性为true 2、如何复制grid类型的所选择的行的数据到系统剪切板&#xff1f;答&#xff1a;string ls_selectedls_selecteddw_1.Object.DataWindow.Sel…

代理对象我所理解的设计模式(C++实现)——代理模式(Proxy Pattern)

文章结束给大家来个程序员笑话&#xff1a;[M] 概述 作为C工程师&#xff0c;免不了要管理内存&#xff0c;内存管理也是C中的难点&#xff0c;而智能指针采用引用计数的方法很方便的帮我们管理了内存的应用&#xff0c;极大方便了我们的任务效率。而智能指针的这类用法其实就是…

suse 内核编译安装_升级SUSE Linux内核的完整步骤!

安装完SLED 10后发现仍然有“热启动网络不通”的问题&#xff0c;原因是内核版本较低&#xff0c;于是升级到2.6.17版内核&#xff0c;成功解决此问题。为了造福广大菜鸟&#xff0c;分享一下我的经验&#xff0c;欢迎高手批评补充。1。将下载的新内核(比如linux-2.6.17.tar.bz…

C语言逆序字符串(递归实现)

算法思想 以字符串“abcdef”为例 1.将a保存到temp中 2.将f放到a的位置 3.f处填写‘\0’ 4.计算bcde的长度 5.如果bcde的长度大于1&#xff0c;则逆序 6.将a放到f的位置 #include <stdio.h> #include<string.h> int my_strlen(char* str) {char* start str;char*…

android 自定义控件

自定义一般分三种情况 1. 自定义布局 2. 自定义控件 3.直接继承View 下面来着eoe例子&#xff0c;实现自定义控件 1. 自定义属性 res/values/attrs.xml 自定义属性 <?xml version"1.0" encoding"utf-8"?> <resources><declare-styleable …

某项目要调用现有的100多个DLL 一 开始

某个项目需要使用很多内部其他Team的DLL 和第三方的DLL (大概百来个吧......这是什么鬼啊...可怕的历史,又不能改 这些dll都上生产环境了) 如果直接用dll引用之后调用 会有很多很多的问题 1.程序的质量会下降到 这百来个dll中质量最差的一个 (万一某些人在代码里面写什么lock(…