我8G DDR4 2400内存, Windows10系统


这个问题我想应该是仁者见仁智者见智的,所以没有必要diss别人的回答,大部分人都可以在自己的经验范围内给出一个合理的参考做法,这是没有问题的,而且应该没有人会说自己是标准答案,因为这本身就没有标准答案。所以我下面不会说「应该设置为XXX」这种话,如果你单纯对此有所期待,那么可以不用费时间向下阅读。

既然这个问题推到我这了,我也凑个热闹稍微说一个个人看法。首先我不是Windows用户,但是虚拟内存不是只有Windows用户才会面临的概念。因为虚拟内存本身是一个操作系统层面的通用概念。在说如何设置虚拟内存之前,我先简单说一下什么是虚拟内存。

先来看一个例子,有这样一个程序:

// mytest.c
#include &
#include &
#include &

int main(int argc, char *argv[])
{
size_t n = 0;

n = atoi(argv[1]);
if (!malloc(n*1024*1024*1024)) {
perror("malloc");
return 1;
}

while(1);

return 0;
}

我们用这个程序来申请内存分配,先来看一下我当前机器的内存情况:

$ free -h
total used free shared buff/cache available
Mem: 15Gi 2.2Gi 9.6Gi 350Mi 3.3Gi 12Gi
Swap: 7.6Gi 0B 7.6Gi

可以看到物理内存有15G左右,当前有12G available,交换空间或者说这个题目所指的「虚拟内存」有7.6G。那么大家觉得我申请分配多少,或导致no memory的错误呢?

首先一次性申请不超过物理内存应该是没有问题的,那一次性申请超过物理内存,但是小于物理内存加「虚拟内存」的总大小呢?

$ ./mytest 18

没有问题,返回成功。那我们一次性申请超过物理内存加「虚拟内存」的总和呢?

$ ./mytest 50
malloc: Cannot allocate memory

这就不行了,系统直接返回错误,告诉你不能分配那么多内存。那我们每次申请5GiB,连续申请十次呢?

$ for i in `seq 1 10`;do ./mytest 5 done

都没有问题,全部成功。为什么一次性申请50G不行,分批就可以呢?因为一次性申请50G,系统直接就能判定没有这么多。但是如果你分开使用,虽然我们每次都申请5G,但系统并没有真的给我们5G,只有在真的需要写入的时候,才会真的让这5G对应物理地址。我们现在可以看到,即使我们做了5G * 10的malloc操作,内存的状态仍然是没有变化:

$ free -h
total used free shared buff/cache available
Mem: 15Gi 2.2Gi 9.6Gi 350Mi 3.3Gi 12Gi
Swap: 7.6Gi 0B 7.6Gi

说明这5G * 10的内存根本没有实际分配。为了让内存得到实际分配,我们对malloc出来的内存进行写入操作,将程序改为:

...
p = malloc(n*1024*1024*1024);
if (!p) {
perror("malloc");
return 1;
}
memset(p, 0xff, n*1024*1024*1024);
...

这回我们先试试分配并写5GB:

$ ./mytest 5
$ free -h
$ free -h
total used free shared buff/cache available
Mem: 15Gi 7.2Gi 4.6Gi 357Mi 3.3Gi 7.2Gi
Swap: 7.6Gi 0B 7.6Gi

可以看到物理内存的used从2.2变成7.2G。如果我们要分配并写超过物理内存大小,但是小于物理内存加上「虚拟内存」大小呢?

$ ./mytest 17
$ free -h
total used free shared buff/cache available
Mem: 15Gi 14Gi 234Mi 83Mi 255Mi 155Mi
Swap: 7.6Gi 4.8Gi 2.8Gi

我们可以看到这么做也是可以的,而且物理内存已经基本全部占用,「虚拟内存」也占用了很大一部分。这时候我写这个回答也变得有一点点卡顿了,因为我的内存已经所剩无多了。但还可以接受,而且渐渐缓解,因为我当前写回答的进程是主要活跃进程,mytest那个测试进程占用的内存应该被部分换出到硬碟上的虚拟内存去了,给我当前的浏览器进程预留了足够的物理内存。

在虚拟内存已经所剩无多的状态下,我们尝试超额申请内存试试,我们一共加起来也就剩3G左右了,我们申请并写入5G试试。注意此时是有风险的,不同的系统可能会有不同的应对方式。在实际这么做之前,我预计我的系统(kernel-5.3.11-100.fc29.x86_64)应该会触发OOM killer,杀死系统认为大量浪费占用内存的进程,以维持系统正常运行(当然不排除误杀我当前的浏览器进程……但我认为概率不大,毕竟上面有一个占了17G的无用进程顶在我前面呢:)。让我们试试看(我先保存个草稿;):

$ ./mytest 5

在经过了一小段时间的卡顿后,这个程序执行成功了,我的浏览器没有被杀死,系统也没有崩溃。而且在预料之内的,那个占用17G内存的程序被内核主动杀死了:

./mytest 17
Killed
$ dmesg
...
[17122.987802] oom-kill:constraint=CONSTRAINT_NONE,nodemask=(null),cpuset=/,mems_allowed=0,global_oom,task_memcg=/user.slice/user-1000.slice/session-2.scope,task=mytest,pid=25832,uid=1000
[17122.987809] Out of memory: Killed process 25832 (mytest) total-vm:17828096kB, anon-rss:11570352kB, file-rss:0kB, shmem-rss:0kB
[17123.578327] oom_reaper: reaped process 25832 (mytest), now anon-rss:0kB, file-rss:0kB, shmem-rss:0kB

通过上述例子,我们可以对物理内存和「虚拟内存」有一个大概的印象。下面我们就来简单说一下什么是虚拟内存。

首先对于计算机技术来说,「虚拟内存」这个概念首先是指一种内存管理的技术方式,而不是指某一个「东西」。虚拟内存顾名思义,就是「虚构的」内存地址空间。这种虚构基于一种映射,进程在运行时面向的地址空间实际上是一层逻辑抽象的连续地址,每一个地址下面可能对应散落的物理内存,可能对应硬碟空间等,当然也可能什么都不对应,下面暂时是空的。在实际进行分配读写时,给需要实际物理内存的虚拟地址分配实际物理内存,暂时不需要实际物理内存的可以暂不分配,物理内存不够时也可以将已经分配的但是暂时不用的内存页写回硬碟,释放其所占用的实际物理内存。这样就保证程序在使用「虚拟」内存地址时不必过于担心实际的物理内存不够的情况。举个不是特别对等的例子,就好像是一个人用三块砖头垫在脚底下走过一片泥泞的道路一样,对于这个人来说他面向的就是一整片连续的道路(虚拟内存),虽然实际砖块(物理内存)很少,但是他可以通过不断把走过的地方的砖往前移动到没走过的地方,来达到一种近似「脚下总有路可以走」的效果。这实际上是虚拟内存的主要目的之一,让进程总觉得自己「有路可走」。甭管里子多忙多疲于奔命,面子上总要先过得去, 这就是好面子的虚拟内存 :)

然后我们在说一下这个问题中,以及日常经常被人提到的「虚拟内存」。上面我们说了,在虚拟内存技术中,硬碟等外部存储介质可以充当虚拟内存地址的临时媒介。所以开始有人将这部分外部存储空间称为虚构的内存,也简称为虚拟内存。所以这里的虚拟内存不是指一种技术,而是指一个东西。当然也有的人将整个内存地址空间都叫「虚拟内存」,因为他们认为使用的本来就是虚拟内存地址,不是实际物理地址。所以「虚拟内存」这个词现在变得很难单独提出来说是指什么,必须在较明确的上下文语境中才能「猜测」其具体代指什么。对于这个问题的语境,它应该是指除物理内存以外,用于交换物理内存页的,位于外存的交换空间,常见的称呼可能包括「虚拟内存」,「交换空间」、「虚存文件」、「页面文件」等等等等。

在早期,程序员处理内存不足的方式是使用一种近乎手动的覆盖技术,比如在几百K的内存空间上需要运行几M大小的程序,程序员需要将这个几M的程序在程序设计和编写时就手动分割,将它们分割为可以独立运行很多部分,然后让它们分时运行,每部分运行时都不超过内存大小。这种技术在现在实际上也没有完全意义上的消亡,这仍然是很多大型程序设计时应该考虑的。

不过这个和我们要说的「虚拟内存」这个东西没太多关系,我们要说的是虚拟内存技术的第二种,自动交换技术。交换技术的目的就是为了让正在或需要马上运行的程序能获得足够的物理内存资源,让不需要运行,或即将退出运行周期的进程让出占用的物理内存资源,将它们暂时保存到外存中去。这个技术就是由内存管理提供的功能,而不需要程序员手动干预。这就有点像你和另一个人分摊房费,分时租住同一个房间似的。

随著技术的发展,我们现在一般不需要以整个进程为粒度进行整体的换入换出,程序的运行也不需要一次性全载入进内存,运行的过程也不需要全部程序都在物理内存上。但是频繁换入换出仍然是性能的瓶颈。为了减缓换入换出带来的影响,增加可用物理内存和增加外存的访问速度是两种可选方案,而且这两种方案不冲突,有条件的完全可以同时选择。说简单了就是买更多的内存,和买更快的SSD等设备。

说了这么多,那么我们回过头说虚拟内存设置,也就是说我们设置多少的用于交换的外存空间更合适呢?可能有1.5~3倍左右物理内存这种说法。但是这个数字不是绝对的,也没有特别大的参考性。一般来说使用默认值就行,个人觉得0.5~2倍都在理论可接受范围内,你也要根据自己的实际内外存储情况进行评估,不能简单的说多少就合适。还是那句话,不懂就默认,除非默认的出现很大问题。如果你发现默认设置下系统卡顿严重,那么你可以尝试通过调整虚拟内存大小来尝试找到一个合适你使用习惯的更好的「值」。这将是综合专业分析的过程,或者是一个「瞎猫碰死耗子」的过程。有时通过调整,确实能达到一定的改善作用,但不绝对,也行你现在默认的就已经是很好的状态了。这时候说明你需要的就是增加物理内存大小,以及换更快的外存储器。


这个问题是没有标准答案的。唯一相对可靠的是系统自行管理。

虚拟内存就是物理内存不够用的时候把一些很少访问的内存数据转存到硬碟上,然后把这部分内存腾出来分配给其它应用。因为硬碟比内存慢的多,只要用虚拟内存就必然卡慢。所以最理想的状态当然是不使用虚拟内存,完全只用物理内存,避免卡慢。

然鹅物理内存有多少,需要多少,很显然每人不同。有人天天打开电脑就追两部剧顺手聊两句QQ,4G就够。有人开一堆虚拟机研究分散式计算的,64G都不够。

如果日常使用程序比较固定,内存需求通常比较稳定的,直接按照需求买稍大容量的物理内存就行。但难免有些时候因为某些特殊原因对内存的需求超出了平常需要。例如写篇文章要查大量资料打开上百个网页标签;临时处理一张超高解析度的照片;平时顶多只用一个虚拟机的但为了某个需要同时开两个甚至三个…

按极端情况的最大需求买内存伤钱,除非矿里有家如 @琴梨梨, 而极端情况到底需要多少内存,又有谁能说的准呢?


我物理内存32G,然后我在C盘设置了48G,在D盘设置了64G。

我情况特殊,我要用3DMAX渲染,如果只是让系统自己管理经常图多的时候就不够,这么设置后就再也没有不够用过。


128m,目的是避免某些睿智程序让我把虚拟内存打开

虚拟内存速度慢,发现内存不足直接加钱买物理内存就完事了


修改:

添加关机自动清除虚拟内存页面文件,这条更实用。

设置步骤如下:

  1. 运行:gpedit.msc进入组策略对象编辑器。
  2. 如图依次打开如下内容:「计算机配置」---「Windows 设置」---「安全设置」---「本地策略」---「安全选项」---「关机:清除虚拟内存页面」。
  3. 右击「属性」点击「已启用」。
  4. 确定,这样设置就ok了。

对于没有组策略的解决方案如下:

  1. 按系统快捷键win+r运行regedit打开注册表编辑器。
  2. 查找到「HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Session Manager/Memory Management」,然后在右边的列表中双击「ClearPageFileAtShutdown」。
  3. 在弹出的「编辑DWORD」值对话框中改为1。
  4. 重新启动计算机,使修改生效。

原答案:

我曾把虚拟内存交给系统自动管理,结果系统慢慢分配了10G的虚拟内存,而本机只有8G内存。结果越用越卡。

每次系统变卡时,查看虚拟内存都是特别大,8G以上。

虚拟内存,本质就是RAM与 硬碟之前的缓存。它不是越大越好。当这个缓存过大时,维持这个缓存就是很耗资源的事情,它使page 在硬碟与RAM 中写入写出增多, 使RAM的命中率降低, 是吃力不讨好的事情。

虚拟内存不会自动清零的,如果虚拟内存的垃圾回收故障,其内存空间越占越大,影响系统性能。

因此,虚拟内存既不应该设置过大,也不应该交系统管理。

怎么办呢?按推荐值写死就好了,减少一些自由度, less is more.


当今内存泛滥的世界,对于个人用户这玩意真的还有存在的意义,不懂。


首先,本人小米pro/8GB,虚拟内存的大小取决于用途,如果只是日常使用,建议设为0。如果需要使用Photoshop处理较高像素图片,或者要大型玩游戏,建议设置得大一点,至少8GB。


虚拟内存是十年前内存奇缺状态下的产物,那时候标配是512到1g的内存,甚至还有更低的,导致运行的程序一多就会不够用。虚拟内存就是将硬碟的部分空间拿来当作内存使用,而硬碟的读写速度和内存差了几个数量级,因此同时运行的程序一多就会非常卡。

家用电脑4G以上内存的几乎不用设置虚拟内存,因为几乎完全够用了。


系统自动。


不建议关,Windows 没有 overcommit,关了有的程序申请不到内存,就出错退出了,设成自动就行了


推荐阅读:
相关文章