emscripten-core / emscripten-core/emscripten

stdout not suitable for heavy data streaming

Open
#16,755 8 comments 0 reactions 0 assignees View on GitHub
Dominant language
C++
Stars
27.6k
Forks
3.6k
Avg merge
1d 1h
Merged PRs (30d)
105

Description

I would like to process GBs of data streamed by wasm app (stdout, stderr, print, printErr) consumed by JS. Preferably JS app receives whole ArrayBuffer/bytes from stdout with each callback, so there is no overhead in terms of loops, converting etc. However, emscripten doesnt seem to be designed for such a flow esp. considering performance. Following is a little research I made with current state of emscripten 3.1.8.

### Module.print/printErr

`stdout` -> `memory (ArrayBuffer)` -> `read by byte in loop` -> `UTF8ArrayToString` -> `print:callback(string)`

Observed seems that wasm stdout, is first stored into memory, iterated by byte, converted to utf and finally recieved. A whole line is eventually received by a callback as a string. This is too much overhead for my case not to mention I am expecting bytes.

### Module.stdout/stderr

`stdout` -> `memory (ArrayBuffer)` -> `read by byte in loop` -> `stdout:callback(singleByte)`

Observed seems that wasm stdout, is first stored into memory, iterated by byte, a single byte is eventually received by a callback. This is still much overhead esp. I need to merge bytes back to ArrayBuffer and process.

### Customized/Hacky Module.stdout/stderr

`stdout` -> `memory (ArrayBuffer)` -> `stdout:callback(arrayBuffer slice)`

Applying modification from https://github.com/emscripten-core/emscripten/issues/16108#issuecomment-1100349079 a whole slice of ArrayBuffer can be delivered at once.

This is as far as I managed to get in terms of performance optimization. I would like to propose the following:

1. provide a new API, so one can attach callback directly on the wasm stdout, so writing data into memory is completely avoided. This will have benefit in terms of performance as well as dedicated memory not being consumed. I am not sure how suitable this with threads etc.

2. or, extend current API (maybe through mounting custom stdout?) so stdout callback works with ArrayBuffer slice instead of a single byte per callback. This will improve performance and the need to post-process the generated JS file by a hack.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.