So, I've been running out of memory with wasm/rust with +atomic flag and wanted to check how much memory is practically available. Here is my crude minimal working example that logs the memory of a vector before it panics:
index.js
import init from './pkg/test1.js';
import * as wasm_test1 from './pkg/test1.js';
async function run() {
await init();
let newDiv = document.createElement("div");
let btn = document.createElement("button");
btn.innerHTML = "Max out the memory now and panic!";
document.body.appendChild(btn);
btn.onclick = function () {
wasm_test1.fill_memory();
};
}
run();
lib.rs
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_namespace = console)]
fn log(s: &str);
}
#[wasm_bindgen]
pub fn fill_memory() {
let mut v = Vec::new();
for i in 1..1000000000 {
v.push(0);
if (i % 10000) == 0 {
let v_size = (std::mem::size_of_val(&*v)/1024/1024).to_string();
log(&format!("{}", v_size+"Mb"));
}
}
std::mem::forget(v);
}
Cargo.toml
..
[lib]
crate-type = ["cdylib"]
[dependencies]
wasm-bindgen = "0.2.80"
wasm-bindgen-futures = "0.4.30"
.cargo/config
[target.wasm32-unknown-unknown]
rustflags = ["-C", "target-feature=+atomics,+bulk-memory,+mutable-globals"]
[unstable]
build-std = ["panic_abort", "std"]
Here is what I observe:
No flags | +atomics | |
---|---|---|
max memory available | 1024Mb | 256Mb |
Browser peak memory consumption (in task manager) | 2550Mb | 750Mb |
Browser idle memory consumption (in task manager) | 225Mb | 225Mb |
Note that +atomics also requires a couple of other flags to be present, but if I remove this flag (and keep the others) the behavior is identical to no flags. The available memory is very precise in the two cases before panic, 256Mb and 1024Mb. So what happens when I set memory flag for higher memory? The memory available with +atomics flag is consistenly, exactly, 1/4th of the total max memory.
I have a few questions:
- Why is the memory 1/4th when using +atomic flag, and what can I do to improve this?
- Why is total memory capped at 1 Gb?
- Why does the browser use 2.5Gb memory when vector is only 1Gb (and maybe with a little overhead)?