Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

High virtual memory usage for each WebAssembly module #41319

Closed
terminal69 opened this issue Dec 25, 2021 · 2 comments
Closed

High virtual memory usage for each WebAssembly module #41319

terminal69 opened this issue Dec 25, 2021 · 2 comments
Labels
memory Issues and PRs related to the memory management or memory footprint. question Issues that look for answers. v8 engine Issues and PRs related to the V8 dependency. wasm Issues and PRs related to WebAssembly.

Comments

@terminal69
Copy link

Version

17.3.0

Platform

Linux localhost.localdomain 5.15.7-1-default #1 SMP Wed Dec 8 08:54:39 UTC 2021 (b92986a) x86_64 x86_64 x86_64 GNU/Linux

Subsystem

WebAssembly

What steps will reproduce the bug?

When loading a simple WebAssembly program that instantiates linear memory, virtual memory usage is 10GB.
For example, the following import.wat

(module
  (memory (import "js" "mem") 1)
  (func (result i32)
    (i32.const 42)
  )
  (export "helloWorld" (func 0))
)

Converted to wasm (import.wasm) and loaded as

const instantiate = async () => {
  const buffer = readFileSync("./import.wasm");
  const module = await WebAssembly.compile(buffer);
  const importObject = {
    js: { mem: new WebAssembly.Memory({ initial: 1, maximum: 1 }) },
  };
  const instance = await WebAssembly.instantiate(module, importObject);
  return instance.exports;
};

The full code for this particular test is available at https://github.com/terminal69/wasm-worker-memory-test/tree/b8d58649e4576f156789bf05aeac15e9ae32af8c as test1d.js

How often does it reproduce? Is there a required condition?

Always

What is the expected behavior?

There should not be a need to reserve 10 gb of memory upfront, especially since maximum memory in WebAssembly is 4 gb. This seems like a bug.

Also when the maximum size of memory is provided, then amount of memory reserved should be adjusted accordingly - although this may not be related to the current issue, and perhaps I should submit this as a feature request.

What do you see instead?

image

Additional information

Due to high virtual memory usage per module, the number of modules that can be loaded in the main thread or in worker threads is limited (piscinajs/piscina#158)

@Mesteery Mesteery added memory Issues and PRs related to the memory management or memory footprint. wasm Issues and PRs related to WebAssembly. labels Dec 25, 2021
@tniessen
Copy link
Member

V8 intentionally allocates a significant amount of virtual memory for each WebAssembly instance (not module!). See, for example, Section 4.3.2 of WebAssembly in Node.js for an explanation.

However, it is only virtual memory. This has no effect on the resident set size (i.e., actual memory usage).

Example:

// WebAssembly module that accesses 4 bytes of memory.
const wasmBytes = Buffer.from('0061736D010000000105016000017F030201000503010001071102046D61696E0000066D656D6F727902000A0C010A00410041002802000F0B0013046E616D6501070100046D61696E0203010000', 'hex');
const module = new WebAssembly.Module(wasmBytes);
// Create 1000 instances and prevent garbage collection.
const instances = Array(1000).fill(0).map((i) => new WebAssembly.Instance(module));

Looking at the /proc/:pid/status file, I see the following stats:

VmPeak: 20972151900 kB
VmSize: 10486392352 kB
VmLck:         0 kB
VmPin:         0 kB
VmHWM:     51956 kB
VmRSS:     51148 kB
RssAnon:   16812 kB
RssFile:   34336 kB
RssShmem:      0 kB
VmData:   160992 kB
VmStk:       132 kB
VmExe:     69352 kB
VmLib:      4040 kB
VmPTE:      8816 kB
VmSwap:        0 kB

V8 has reserved 10486392352 kB of virtual memory, i.e., approximately 10000 GiB or 10 GiB per instance, on a system that has a total of 12 GiB of usable memory (main memory + swap). The resident set size (i.e., the actual memory usage) remains at approximately 50 MiB.

@tniessen tniessen added question Issues that look for answers. v8 engine Issues and PRs related to the V8 dependency. labels Dec 25, 2021
@terminal69
Copy link
Author

Thank you for the clarification.

In earlier versions of nodejs (prior to 17.2) trying to start a new instance once virtual memory is above 1000 GiB would result in an Out of memory: wasm memory error, limiting to about 100 WebAssembly instances.

With nodejs 17.2.0 and 17.3.0 I can start 1000 worker threads (each one loading the same wasm) on the same system.

I am not sure if high virtual memory usage would be a problem for some containerized applications.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
memory Issues and PRs related to the memory management or memory footprint. question Issues that look for answers. v8 engine Issues and PRs related to the V8 dependency. wasm Issues and PRs related to WebAssembly.
Projects
None yet
Development

No branches or pull requests

3 participants