为什么关闭虚拟内存并不能提高我的计算机性能?

为什么关闭虚拟内存并不能提高我的计算机性能?

我正在研究计算机架构,更具体地说是虚拟内存。有一件事我似乎无法理解为什么关闭虚拟内存并不能提高我的计算机性能

我知道禁用虚拟内存有一些缺点(例如,Windows 将无法创建崩溃转储),但它不是应该加快我的系统速度吗?

如果我使用虚拟内存,每次访问 RAM 时我的内存管理单元必须再次访问主内存(或至少传输层协议)以便将我的虚拟地址转换为硬件地址(对吗?)。

因此,假设我有足够的 RAM,禁用虚拟内存是否不应该阻止这种对内存的额外访问(因为我不再需要将我的地址从虚拟地址转换为物理地址)从而加快我的系统速度?

答案1

因为虚拟内存不仅仅是页面文件。

您只是移除了允许系统将内存推送到磁盘的存储设备,并且您不能“仅仅”禁用现代操作系统上的虚拟内存。

操作系统使用虚拟内存将应用程序隔离到其自己的地址空间中,从而加强安全性。

通过为应用程序提供自己的地址空间每一个应用程序可以访问其整个地址范围,而不必与其他应用程序争夺内存区域。

内存隔离和写时复制保护意味着两个应用程序可以共享相同的库并使用几乎相同的代码集,但彼此之间完全受到保护。一个程序崩溃或执行不该执行的操作不会导致另一个程序也崩溃。

您的系统总是使用虚拟内存,因为它是任何现代操作系统设计中的关键组件。

答案2

为什么关闭虚拟内存并不能提高我的计算机性能?

当你在 Windows 中执行此操作时,你实际上做的是禁用页面文件。您告诉操作系统它不应再将其认为较少使用的页面暂时移出到磁盘。

这实际上会降低您的计算机速度,因为它会将可能不常用的东西保存在 RAM 中,而不是保存在磁盘上并在需要时进行交换。

这不会禁用 MMU。当系统在保护模式下运行时,MMU 始终被使用且需要,以实现进程分离、防止页面中的数据作为代码执行的“NX”功能以及其他功能。


任何内存访问都会比片上功能慢。这是开发 RISC 型 CPU 时的考虑因素之一 - 将一堆寄存器放在芯片上,这样可以减少对 RAM 的访问。

AMD64 CPU 引入的一项改进是增加了更多寄存器,这意味着无需使用 RAM 作为暂存器即可执行更多操作。现代 CPU 还具有大量非常宽的 SIMD/AVX/EVEX 寄存器。现代 x86 CPU 上有许多非 RAM 计算选项。

无论如何,除非被禁用,否则 CPU RAM 访问无论如何都会首先利用内部 L1 缓存,由于它实际上与 CPU 位于同一芯片上,因此速度非常快。

通过禁用 MMU/TLB 所获得的任何速度提升都将非常小,并且您将无法保护内存免受其他进程的侵害。

答案3

您无法超越操作系统的虚拟内存管理,无论是 Windows、Mac 还是 Linux。

除非绝对需要,否则操作系统不会将数据存储在页面/交换文件中。启用页面文件不会对性能造成影响,因为它仅在需要时在后台使用。

如果您的计算机频繁访问页面/交换文件以致计算机速度变慢,那么删除该文件不会有任何帮助,只会导致您的应用程序或操作系统在内存不足时崩溃。

此外,禁用页面/交换文件不会禁用“虚拟内存”。虚拟内存是一种允许分页/交换的内存寻址概念,但无论您是否启用页面文件,它仍会被使用。

答案4

到目前为止,答案中有几点正确之处,但是却忽略了一个重要点。

正如其他人所说,禁用页面文件不会关闭虚拟内存。地址转换(通过页表)以及我们从中获得的一切(单独的进程地址空间、每页读/写和内核/用户内存保护、“不执行”位等)仍将发生。

还没有人提到禁用页面文件也不会关闭分页 IO。即使没有页面文件,磁盘的分页仍将发生。至少在 Windows 上,演示这一点很容易。禁用页面文件,重新启动,启动性能监视器 (perfmon.exe),查看内存对象下的分页 IO 计数器,然后开始运行一些程序。

怎么会这样?因为页面文件不是唯一参与分页或分页 IO 的文件!

分页 IO 还涉及哪些文件?映射文件。“映射文件”包括所有代码文件 - 在 Windows 上,主要是 exe 和 dll。

当你开始运行一个程序或将 dll 加载到现有进程中时,代码并不会简单地全部复制到 RAM 中。(Windows API 名称为“LoadLibary”除外。)代码文件只是映射进入你的地址空间。读操作是由分页器进行的,它是为了响应页面错误而进行的。页面错误发生在从尚未分页的代码页中获取指令时。换句话说,代码是请求分页像虚拟内存中的其他内容一样进入 RAM(即,实际上未执行的大部分代码不会被带入)。

(我在这里省略了对预取程序的提及,但这实际上并没有改变所描述的原则。代码仍然是按需分页的,预取程序只是试图在进程的生命周期内更快地实现它。)

如果某些代码被分页,而 RAM 后来变得稀缺,一些已经分页的内容需要从 RAM 中“驱逐”出来,为新内容腾出空间,那么包含代码的页面就会像数据页一样被分页出。

唯一的区别是,包含代码的页面在 RAM 中通常不会更改一次,如果它们没有被更改,则在它们重新用于其他用途之前无需在任何地方写入。如果它们被内存管理器回收,然后稍后再次需要,它们可以(并且确实)从它们来自的 exe 或 dll 文件中调回。

数据文件(尤其是大型数据文件)也经常通过文件映射来访问。相关的 *nix 调用是 mmap(),在 Windows 中是 CreateFileMapping 或 OpenFileMapping,以及 MapViewOfFile。此类映射通常是读/写。如果此类映射中的页面在 RAM 中被修改,那么当这些页面必须从 RAM 中移出时,它们将被写回到其原始文件中。页面文件不参与其中。

除非它们被映射为写时复制我不会在这里详细说明,只能说它们由页面文件支持(如果您有的话)。

对于给定的工作负载和给定的 RAM 量,将存在一定数量的分页。关闭页面文件只是意味着所有页面都将转移到映射文件,而不是一些页面转移到映射文件,一些页面转移到页面文件。但这仍会发生。因此,您会发现,没有页面文件时,分页 IO 的数量与有页面文件时一样多。

这就是为什么关闭页面文件不会对性能产生太大影响的原因。

事实上,它会让情况变得更糟。如果没有页面文件,当需要将页面调入磁盘时,就必须将页面调入映射文件。结果:每个进程曾经修改过的每个非共享页面都必须保存在 RAM 中,直到修改它的进程退出。包括堆栈底部的陈旧内容等,这些内容可能永远不会再被引用。分页器无法考虑将这些页面逐出(无论它们是多好的选择),因为没有其他地方可以存储它们的内容。

顺便说一下,页面写作通常不会造成太大的瓶颈。写入页面文件或映射文件几乎是免费的(应用程序代码不必在写入时阻塞;它会在单独的线程中运行)。真正减慢您工作速度的是页面程序必须读取磁盘时 - 即当它必须解析难的页面错误。当然,这种情况可能发生在页面文件和映射文件(包括代码文件)上——无论后备存储为错误页面。

再次强调:Windows 中的分页 IO 计数器会告诉您发生了多少分页 IO。如果没有分页文件,它们就不会为零。

至于 OP 问题中关于避免地址转换、读取页表条目等开销的方面 - 开销非常小。据测量,它不到 2%。原因是转换缓冲区 (TLB) 缓存做了它应该做的事情。

相关内容