【问题标题】:Why do Rust programs use so much more memory than the C, Haskell and OCaml versions?为什么 Rust 程序比 C、Haskell 和 OCaml 版本使用更多的内存?
【发布时间】:2015-12-22 02:25:28
【问题描述】:

我查看了 Rust 程序使用了多少内存(top 命令中的RES 列),我想知道它们为什么使用这么多内存。

这是一个例子:

use std::io;

fn main() {
    println!("What's your name?");
    let mut input = String::new();
    io::stdin().read_line(&mut input).unwrap();
    println!("Hello {}!", input);
}

我在输入内容之前看到使用了 6 MB 的内存。

这是我编译和执行程序的方式:

cargo build --release
./target/release/main

等效的C程序:

#include <stdio.h>

int main(void) {
    printf("What's your name?\n");
    char input[100] = {0};
    scanf("%s", input);
    printf("Hello %s!\n", input);
    return 0;
}

仅使用 0.6 MB。在这种情况下,Rust 程序使用了 10 倍以上的内存。在其他情况下,我看到 Rust 程序使用了 5 倍以上的内存。

我还测试了与其他语言进行比较。

OCaml 版本:

let () =
    print_endline "What's your name?";
    let line = read_line () in
    print_string "Hello ";
    print_endline line

使用 1 MB。

Haskell 版本:

main = do
    putStrLn "What's your name?"
    name <- getLine
    putStrLn ("Hello " ++ name ++ "!")

使用 3 MB。

Python 版本:

print("What's your name?")
name = input()
print("Hello", name, "!")

使用 7 MB,与 Rust 版本几乎相同!

更新

我正在运行带有 Rust 1.3 的 Linux (ArchLinux)(我也尝试了 nightly,结果相似)。

更新 2

以下是来自htop 命令的更多数据:

VIRT    RES     SHR     MEM%    Command
15572   2936    804     0.1     ocaml
21728   2732    2528    0.1     haskell
22540   7480    4308    0.2     python
4056    668     600     0.0     c
24180   6164    1928    0.2     rust

更新 3

我对@9​​87654345@ 进行了更多测试以查看内存使用情况。

对于每个程序,我都运行了两次massif,如下:

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

这是所有程序的结果(如ms_print所示):

C 版本:

https://framabin.org/?dd243f8ec99155bc#Af5cPrcHnz3DsWiOStfwgW8Qq6BTVhogz/46L+sMuSs=

https://framabin.org/?261b9366c3749469#1ztDBkgVly9CanrrWWrJdh3yBFL5PEIW3OI5OLnze/Q=

Rust 版本:

https://framabin.org/?0f1bac1c750e97bf#AXwlFYYPHeazq9LfsTOpRBaUTTkb1NfN9ExPorDJud0=

https://framabin.org/?c24b21b01af36782#OLFWdwLjVG2t7eoLqLFhe0Pp8Q8pA2S/oq4jdRRWPzI=

OCaml 版本:

https://framabin.org/?060f05bea318109c#/OJQ8reHCU3CzzJ5NCOCLOYJQFnA1VgxqAIVjgQWX9I=

https://framabin.org/?8ff1ffb6d03cb37a#GN8bq3Wrm6tNWaINIhMAr4ieltLtOPjuZ4Ynof9bV4w=

Haskell 版本:

https://framabin.org/?b204bd978b8c1fd8#DyQH862AM8NEPTKlzEcZgoapPaZLdlF9W3dRn47K5yU=

https://framabin.org/?ac1aa89fcaeb782c#TQ+uAiqerjHuuEEIhehVitjm63nc3wu5wfivAeBH5uI=

Python 版本:

https://framabin.org/?197e8b90df5373ec#aOi0+tEj32Na5jW66Kl97q2lsjSZ2x7Cwl/pOt0lYIM=

https://framabin.org/?397efa22484e3992#1ylOrmjKaA9Hg7gw7H7rKGM0MyxuvKwPNN1J/jLEMrk=

总结(内存使用):

|------------|----------|----------|----------|----------|----------|
|            |     C    | Haskell  |   OCaml  |   Rust   |  Python  |
|------------|----------|----------|----------|----------|----------|
| First run  |    1 B   | 63.12 KB | 5.993 MB |   816 B  | 1.321 MB |
|------------|----------|----------|----------|----------|----------|
| Second run | 6.031 MB | 24.20 MB | 17.14 MB | 25.60 MB | 27.43 MB |
|------------|----------|----------|----------|----------|----------|

第一次运行没有--pages-as-heap=yes 参数。

我还为 C 和 Rust 运行了 massif--stacks=yes 选项。

C 版:

https://framabin.org/?b3009d198ccfdee1#HxR6LPPAzt15K+wIFdaqlfSJjBrJvhV2ZHWdElg3ezc=

(3.141 KB)

Rust 版本:

https://framabin.org/?b446d8d76c279007#tHnGiOnRstTA2krhz6cgfvTjI+FclcZS3rqyZvquWdQ=

(8.602 KB)

如何解释 Rust 中堆块分配和页面分配之间如此巨大的差异?

【问题讨论】:

  • 直到达到GB的范围,有什么问题(假设不在嵌入式平台上运行)?您是否测试了越来越大的程序并发现它的扩展性仍然相同?还是由于运行时环境而存在一些“最小值”,然后它可以合理地扩展?
  • 在 OS X 上,使用 Rust 1.3,您的 Rust 程序根据顶部使用 660K。您可能应该 edit 您的问题包含这些详细信息。
  • @crashmstr 如果运行时的固定开销对于 rust 来说大于例如哈斯克尔。
  • 当然,它们并不完全相同。目前,C 版本正在等待成为缓冲区溢出漏洞,我认为 Rust 版本不是。即使您解决了该问题(通过指定宽度),如果您的姓名长度为 10000 个字符,您仍然会得到明显不同的行为。
  • 可以确认 rust 对于具有假定为零大小的运行时的编译语言具有较高的初始内存要求。有关测量的示例,请参阅benchmarksgame.alioth.debian.org/u64q/rust.html - 它们显示出非常相似的内存消耗模式。请注意,静态链接无法解释差异,例如到 C. 也许是由于 linux 上的 jemalloc 设置?

标签: rust


【解决方案1】:

因为标准库是静态链接的。

您可以通过使用-C prefer-dynamic 选项进行编译来克服这个问题。

关于静态链接标准库的原因:它增加了可执行的可移植性(即:不需要在目标系统中安装标准库)。

【讨论】:

  • 使用这个选项,有一些变化,但它仍然比 Haskell 和 OCaml 版本使用更多的 RAM。 The only ways that were found to reduce the RAM usage was to use the system allocator or the no_std feature,但它没有解释为什么 Rust 默认使用更多 RAM。
  • 可能还有很多内联
  • 对于这样一个简单的程序,标准库不会出错。 jemalloc 是一个更可能的解释。
  • 当时,Windows 可执行文件也更大,当时 jemalloc 还没有 rust for Windows。 (我过去谈过,因为我已经有一段时间没有使用 rust 了;jemalloc 可能还没有在 Rust for windows 中使用)
  • 为什么stdlib是完整链接的?如果只使用控制台 io?
【解决方案2】:

This article 对这个话题进行了很好的讨论。一些最大和最常见的罪魁祸首是 cargo 默认调试构建(与您的情况无关)和默认静态包含库。

【讨论】:

    猜你喜欢
    • 2018-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多