当使用 +atomics 标志 web assembly 编译 rust wasm 时,只有最大内存的 1/4 可用

ste*_*kwr 5 rust webassembly rayon wasm-bindgen

因此,我使用带有 +atomic 标志的 wasm/rust 时内存不足,想检查实际可用的内存量。这是我的粗略的最小工作示例,它在向量发生恐慌之前记录其内存:

索引.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();
Run Code Online (Sandbox Code Playgroud)

库文件

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);
}
Run Code Online (Sandbox Code Playgroud)

Cargo.toml

..
[lib]
crate-type = ["cdylib"]

[dependencies]
wasm-bindgen = "0.2.80"
wasm-bindgen-futures = "0.4.30"
Run Code Online (Sandbox Code Playgroud)

.cargo/配置

[target.wasm32-unknown-unknown]
rustflags = ["-C", "target-feature=+atomics,+bulk-memory,+mutable-globals"]

[unstable]
build-std = ["panic_abort", "std"]
Run Code Online (Sandbox Code Playgroud)

这是我观察到的:

无旗帜 +原子
最大可用内存 1024MB 256MB
浏览器峰值内存消耗(在任务管理器中) 2550MB 750MB
浏览器空闲内存消耗(在任务管理器中) 225MB 225MB

请注意,+atomics 还需要存在几个其他标志,但如果我删除此标志(并保留其他标志),则行为与没有标志相同。在发生恐慌之前的两种情况下,可用内存非常精确:256Mb 和 1024Mb。那么当我将内存标志设置为更高内存时会发生什么?+atomic 标志可用的内存始终准确地为总最大内存的 1/4。

我有几个问题:

  • 为什么使用 +atomic 标志时内存为 1/4,我可以做些什么来改善这个问题?
  • 为什么总内存上限为 1 Gb?
  • 为什么浏览器使用 2.5Gb 内存,而矢量只有 1Gb(可能还有一点开销)?

ste*_*kwr 5

对于在这里遇到这个问题的任何人来说,这里有几个问题在起作用。最终,我能够夺回所有的记忆。

  1. 看来 Rust 中动态分配的向量的工作方式是,当元素被推送并且当前空间用完时,分配会加倍。因此,尽管还有更多可用内存,但它在接近一半内存时出现恐慌。::with_capacity 帮助我解决了这个问题
  2. rust 编译器中存在某种默认设置,其中 +atomics 标志将内存上限设置为 1Gb。您可以通过添加 rust 标志来更改货物配置文件中的默认设置,如下所示以获得 4G(chrome 允许 WASM 的最大值):
rustflags = ["-C", "target-feature=+atomics,+bulk-memory,+mutable-globals", "-C",
 "link-arg=--max-memory=4294967296"]
Run Code Online (Sandbox Code Playgroud)