测量内存使用情况:虚拟内存与实内存

2021-08-02 05:59:23

软件开发人员经常关心他们的应用程序的内存使用情况,这是正确的。使用过多内存的软件可能会失败或运行缓慢。内存分配在所有系统下都不会以相同的方式工作。但是,在较高级别上,大多数现代操作系统都具有虚拟内存和物理内存 (RAM)。当您编写软件时,您在地址处读取和写入内存。在现代系统上,这些地址是 64 位整数。出于所有实际目的,您有无数个这样的地址:每个正在运行的程序可以访问数百 TB。但是,此内存是虚拟的。很容易忘记虚拟的意思。这意味着我们模拟了一些并不存在的东西。因此,如果您使用 C 或 C++ 进行编程并分配了 100 MB,则您可能根本不会使用 100 MB 的实内存。以下代码行可能根本不消耗任何实际内存: 当然,如果您在这些“虚拟”内存地址上写入或读取内存,一些真实内存将发挥作用。您可能认为如果您分配一个跨越 32 个字节的对象,您的应用程序可能会收到 32 个字节的实内存。但是操作系统不能以如此精细的粒度工作。相反,它们以“页面”为单位分配内存。页面有多大取决于您的操作系统和正在运行的进程的配置。在 PC 上,页面通常小至 4 kB,但在 ARM 系统上通常更大。操作系统允许您请求大页面(例如,1 GB)。您的应用程序以页面为单位接收“真实”内存。您永远无法从操作系统中获得“32 字节”的内存。这意味着微优化应用程序的内存使用是没有意义的:您应该从页面的角度考虑。此外,接收内存页面是一个相对昂贵的过程。因此,如果效率对您很重要,您可能不想不断地获取和释放内存。一旦分配了虚拟内存,我们能否预测以下循环中的实际(真实)内存使用情况?结果将取决于您的系统。但是一个简单的模型如下:计算您访问的连续页面的数量,假设您的指针从页面的开头开始。页面使用的内存是进程内存使用的下限,假设系统不使用其他技巧(如内存压缩或其他启发式)。

我在 Linux 下编写了一个 C++ 小程序,它在循环内定期打印出内存使用情况。我使用了大约 100 个样本。如下图所示,我的模型(由绿线表示)是进程实际内存使用情况的出色预测器。因此,考虑内存使用情况的一种合理方法是计算您访问的页面。页面越大,此模型的成本就越高。因此,如果您想节省内存使用量,似乎可以使用较小的页面。然而,像 Apple 的 iOS 这样的移动操作系统的页面 (16 kb) 比大多数 PC (4 kb) 大。如果有选择,我几乎总是选择更大的页面,因为它们使内存分配和访问成本更低。此外,您可能不必太担心虚拟内存。不要盲目计算您的应用程序请求的地址范围。它可能与您的实际内存使用几乎没有关系。现代系统拥有大量内存和非常聪明的内存分配技术。关注应用程序的整体内存使用情况是明智的,但与通过微观优化问题相比,您更有可能在软件架构级别解决内存问题。