Description
When compiling a project of mine, my PC with 32GB of RAM went OOM. I reduced the problem to the following code:
use std::collections::HashMap;
static TESTDATA: &str = include_str!("../testdata");
fn parse_testdata() -> HashMap<(), ()> {
let mut map = HashMap::new();
for line in TESTDATA.lines() {
}
map
}
pub fn do_stuff() {
let (tx, _) = std::sync::mpsc::channel();
let testdata = parse_testdata();
tx.send(vec![0]).unwrap();
}
fn main() {
do_stuff();
}
Compiling this code with /usr/bin/time -v cargo build --release
shows a maximum resident RAM usage of 16GB if testdata is generated with python -c "print('foo bar baz qux 1337 42\n' * 4_500_000)" > testdata
(103MB). In debug mode, only 1.3GB RAM are used. It doesn't matter if edition is 2018 or not.
Here are some different testdata sizes with their compilation memory usage:
python generation | size | RAM | comment |
---|---|---|---|
'foo bar baz qux 1337 42\n' * 4_500_000 |
103MB | 16GB | file structure similar to my real-world use-case |
'foo bar baz qux 1337 42 ' * 4_500_000 |
103MB | 16GB | newlines don't matter |
'a' * 100*1024*1024 |
100MB | 15.7GB | we can reduce this to simple file size |
'a' * 80*1024*1024 |
80MB | 14GB | |
'a' * 50*1024*1024 |
50MB | 8GB | |
'a' * 25*1024*1024 |
25MB | 3.9GB | |
'a' * 10*1024*1024 |
10MB | 1.9GB | |
'a' * 1*1024*1024 |
1MB | 256MB |
If anything in the code is changed, the problem gets slightly better. Here is the RAM usage after some small changes for 100MB (for comparison, include_str
just with a hello-world requires 670MB):
- use a
Vec
instead of theHashMap
: 2.5GB - create the HashMap at the end of of the
parse_testdata
function: 6GB - inline the
parse_testdata
function manually: 6GB - make
parse_testdata
not return anything and remove the HashMap from the function: 2.5GB - send
()
instead ofvec![0]
: 6GB - remove the channel creation and sending into it: 4.4GB
- don't call
do_stuff
: 672MB
Meta
uname -a
: Linux 5.5.4-arch1-1-vfio #1 SMP PREEMPT Wed, 19 Feb 2020 15:49:02 +0000 x86_64 GNU/Linux
(Archlinux)
Tested on (always testing with 100MB):
- current stable:
rustc 1.42.0 (b8cedc004 2020-03-09)
: 16GB - current nightly:
rustc 1.43.0-nightly (45ebd5808 2020-03-15)
: 16GB rustc 1.41.1 (f3e1a954d 2020-02-24)
: 16GBrustc 1.41.0 (5e1a79984 2020-01-27)
: 16GBrustc 1.40.0 (73528e339 2019-12-16)
: 2.5GBrustc 1.39.0 (4560ea788 2019-11-04)
: 2.5GBrustc 1.38.0 (625451e37 2019-09-23)
: 6GBrustc 1.35.0 (3c235d560 2019-05-20)
: 6GBrustc 1.34.0 (91856ed52 2019-04-10)
: 6GBrustc 1.32.0 (9fda7c223 2019-01-16)
: 8GBrustc 1.30.0 (da5f414c2 2018-10-24)
: 5GB