emscripten-core / emscripten

Emscripten: An LLVM-to-WebAssembly Compiler
Other
25.8k stars 3.31k forks source link

Paid support from emscripten devs #19470

Closed andyb1979 closed 1 year ago

andyb1979 commented 1 year ago

Hi all

we’re using emscripten in a commercial project and hitting some issues with memory usage. Specifically seeing wasm heap grow and not shrink. (See https://github.com/WebAssembly/design/issues/1397)

I understated the reasons for this however to our users it’s not acceptable. We need a way to let them free memory

do the main contributors of emscripten offer any paid support services? With expert advice we may be able to solve this

juj commented 1 year ago

I'd be super happy to take all your money, though unfortunately this is not an issue that we could fix in Emscripten repository side by some work, but it will need to be something that gets fixed in the WebAssembly specification itself.

You can try commenting on the design issue item with a "we are affected too and would like to see a resolution" sentiment. In that thread, the consensus was not positive towards adding a shrink operation to the memory, but a memory discard operation would allow releasing pages in the middle back to the OS. This means that 64-bit browsers would be helped by the discard proposal, although 32-bit browsers would still have no way to shrink the address space reservation.

If possible, give the experimental emmalloc discard branch from juj/emmalloc a try on Firefox Nightly with the javascript.options.wasm_memory_control flag enabled in about:config to see if that'll help your scenario.

andyb1979 commented 1 year ago

Shucks, I was really looking forward to giving someone all my money 😆

Joking, yes I appreciate that. Rather than changes to emsdk or Webassembly spec, I was rather thinking we try something different which involves some expertise about how we use wasm.

the issue essentially boils down to new/delete of large arrays of doubles in wasm. Eventually memory fragmentation occurs and we run out of memory despite having freed the blocks.

An idea I have is to separate large allocations into a shared module and collect/delete just that module when finished. I’m open to other suggestions as well. This would be easier with an expert in emsdk or wasm to assist.

sbc100 commented 1 year ago

Its sounds like are you are talking about memory fragmentation within the linear memory. If so, that that is probably something that can be addressed within your application rather than needing a wasm spec change. Solutions such as arena allocators (what dlmalloc calls mspaces) or stack allocators (bump allocators) are something used to solve internal fragmentation issues.

andyb1979 commented 1 year ago

I wonder if simply exposing a delete() function on the WebAssembly module or instance would be enough?

At a minimum we want to dispose and reclaim wasm memory once we're done with the wasm instance which means the application state will be at a point where we won't be using that wasm Instance again. It's very hard to get the browser to release memory just by referenes to the wasm instance, as references can be out of your control (e.g. third party tools, libraries and code can hold a reference to a wasm Instance object)

for example just

wasmInstance.delete(); // Permanently delete/collect the wasm heap. This wasm instance will be unusable

would be a solution

or even

wasmMemory.delete();
sbc100 commented 1 year ago

I wonder if simply exposing a delete() function on the WebAssembly module or instance would be enough?

At a minimum we want to dispose and reclaim wasm memory once we're done with the wasm instance which means the application state will be at a point where we won't be using that wasm Instance again. It's very hard to get the browser to release memory just by referenes to the wasm instance, as references can be out of your control (e.g. third party tools, libraries and code can hold a reference to a wasm Instance object)

for example just

wasmInstance.delete(); // Permanently delete/collect the wasm heap. This wasm instance will be unusable

would be a solution

or even

wasmMemory.delete();

That is not something that exists in the WebAssembly JS API.. JS depends on GC to detect references and free resources automatically. Adding this API would require a change to WebAssembly spec and is not something that emscripten could do.

I would also imagine I might not get a lot of support but if you want to propose adding such an API thing the right place to do it would be over in the spec repo: https://github.com/WebAssembly/spec/tree/main/document/js-api

andyb1979 commented 1 year ago

Will close the issue, thanks for pointing in the right direction. We will focus on (1) removing all references to wasmInstance and (2) if necessary another allocator

andyb1979 commented 1 year ago

Confirmed - removing all references to wasmInstance so that it is GC'd by JavaScript causes wasm heap to be deleted. One caveat, this patch for Safari causes a GC Root to wasmInstance so must be disabled