Подтвердить что ты не робот

Почему программы Rust используют гораздо больше памяти, чем версии C, Haskell и OCaml?

Я посмотрел, сколько RAM использовалось программами Rust (колонка RES из top), и мне интересно, почему они используют так много памяти.

Вот пример:

use std::io;

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

Я видел, что 6 МБ памяти использовалось до ввода чего-то.

Вот как я скомпилировал и выполнил программу:

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

Эквивалентная программа на C:

#include <stdio.h>

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

используется только 0,6 МБ. В этом случае программа Rust использует в 10 раз больше памяти. В других случаях я видел, что программа Rust использует в 5 раз больше памяти.

Я также тестировал другие языки для сравнения.

Версия OCaml:

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

использует 1 МБ.

Версия Haskell:

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

использует 3 МБ.

Версия Python:

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

использует 7 МБ, почти так же, как версия Rust!

Update

Я запускаю Linux (ArchLinux) с Rust 1.3 (я также пробовал ночные с аналогичными результатами).

Обновление 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

Я сделал больше тестов с помощью massif, чтобы увидеть использование памяти.

Для каждой программы я дважды запускал 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=

Варианты ржавчины:

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.

Я также запускал massif с опцией --stacks=yes для C и Rust.

Версия C:

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

(3.141 KB)

Версия ржавчины:

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

(8.602 KB)

Что объясняет такую ​​огромную разницу между распределением блоков кучи и распределением страниц в Rust?

4b9b3361

Ответ 1

Поскольку стандартная библиотека статически связана.

Вы можете преодолеть это путем компиляции с помощью параметра -C prefer-dynamic.

В связи с тем, что стандартная библиотека статически связана: она увеличивает допустимую переносимость (т.е. нет необходимости устанавливать стандартную библиотеку в целевой системе).

Ответ 2

В этой статье есть очень хорошее обсуждение темы. Некоторые из крупнейших и наиболее распространенных преступников - это по умолчанию дефолты для отладки (не соответствующие вашему делу) и статически включающие библиотеки по умолчанию.