3

我正在尝试测量我正在编写的 rust 程序的内存大小。我注意到,当我使用以下命令测量堆大小时:

valgrind --tool=massif --pages-as-heap=yes ./program

并使用 ms_print 进行测量,内存大小非常大(最初约为 16MB)。最终,我将我的 rust 程序简化为一个空的 main 函数:

fn main() {
}

我编译了,仍然有 16MB 作为我的内存大小。我注意到,当我使用不同的机器时,相同的二进制文件的总大小为 4MB。我的一个朋友在他的机器上用相同的程序尝试了这个,使用相同的 rust/valgrind 版本,也得到了 4MB 的大小。

我想这是对可能在堆中使用的内存的某种预分配,但我想不出任何控制它的方法。我什至尝试按照指南更改分配器,但没有任何改变。

系统详情:

OS version       = Ubuntu 18.04
valgrind version = valgrind-3.13.0
cargo version    = cargo 1.39.0-nightly (3f700ec43 2019-08-19)
rustc version    = rustc 1.39.0-nightly (e44fdf979 2019-08-21)
ms_print         = ms_print-3.13.0
libc version     = ldd (Ubuntu GLIBC 2.27-3ubuntu1) 2.27
4

1 回答 1

9

pages-as-heap由于对大多数现代操作系统(尤其是 linux)上的页面管理的工作方式存在误解,导致您出错的地方是。这并非适用于所有平台,取决于分配器、底层平台和 MMU。在实践中,如果您的平台支持虚拟内存,您很可能会遇到这样的情况。

页面并不总是内存中的强制保留区域。大多数内存函数(mmap以及malloc其他一些函数)将分配内存,但这只会被操作系统/内核视为指示性的。您可以通过以下测试说服自己:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv) {
  void *ptr = malloc(1024 * 1024 * 1024);
  sleep(100);
  return 0;
}

运行几次,然后...

:~# free -m
              total        used        free      shared  buff/cache   available
Mem:          15930        1716        5553         170        8661       13752
Swap:             0           0           0
:~# ./hog &
[1] 27577
...
[99] 27674
:~# free -m
              total        used        free      shared  buff/cache   available
Mem:          15930        1717        5552         170        8661       13751
Swap:             0           0           0

您可以在 中复制此测试rust,但您需要比通常在抽象中进行的操作稍微深入一些才能实现此目的:

fn main() {
  let mut vec:Vec<u8> = vec![];
  vec.reserve(1024 * 1024 * 1024);
}

内存只有在初始化访问后才重要。那时,操作系统知道你真的想要它,并将它一直分配给硬件。Rust 也不例外——除非你使用了一些堆,否则堆只是mmap内核中指向虚拟内存的一个。

因此,通过使用该pages-as-heap参数,您只是在完成任何重新分配之前寻找“潜在”内存,而不是实际使用的内存。删除这个参数,你会看到你的程序消耗了大约 300 字节的堆(你可以很容易地valgrind自己分析)。

您的朋友看到​​不同输出的原因是因为他们的页面大小为 4kB,而您的页面大小为 16kB。稍后我将在 rustc 源代码中找到确切的点——rust 分配了 1024 页。

于 2019-09-19T10:00:57.820 回答