Skip to content

wasm-runner: add lazy stream/4 for resource-managed WASM streaming#18

Open
yevbar wants to merge 4 commits intomasterfrom
sleepy/wasm-runner-stream
Open

wasm-runner: add lazy stream/4 for resource-managed WASM streaming#18
yevbar wants to merge 4 commits intomasterfrom
sleepy/wasm-runner-stream

Conversation

@yevbar
Copy link
Copy Markdown
Contributor

@yevbar yevbar commented Feb 28, 2026

By Sleepy

What

Adds WasmRunner.stream/4 — a lazy stream that applies a WASM function over argument lists with automatic instance lifecycle management.

Why

map/4 eagerly evaluates all calls and collects results into a list. For large or unbounded input sets, this wastes memory. Firebird.Stream requires manual instance management. stream/4 fills this gap.

How

Uses Stream.resource/3 to:

  • Load the WASM instance lazily on first element consumed
  • Call the function one-at-a-time as elements are pulled
  • Automatically stop the instance when the stream ends or is halted early

Composes naturally with all Elixir Stream and Enum functions.

Tests

16 new tests covering:

  • Basic usage and empty input
  • Early termination (Enum.take, Enum.find, Stream.take_while)
  • Stream composition (filter, map, chunk_every, with_index, zip)
  • Aggregation (Enum.reduce, Enum.count)
  • Cleanup guarantees (full consumption and early halt)
  • Equivalence with map/4 for full consumption

Sleepy added 4 commits February 28, 2026 22:02
…lpers

Add ergonomic collection operations to WasmRunner that load a WASM module
once and apply a function across multiple inputs:

- run/4, run!/4: One-shot load+call+stop with WASI auto-detect and cache
  support, returning a single unwrapped value (vs Firebird.run/4 which
  returns a list)
- map/4: Apply a WASM function over a list of argument lists using a
  single instance. Supports parallel execution via :concurrency option.
- flat_map/5: Map + filter in a single pass over inputs
- reduce/6: Fold WASM function results through an Elixir accumulator

All functions accept file paths, raw bytes, or precompiled modules.

By Sleepy
- Run mix format across all files (Elixir 1.16 formatting rules)
- Fix unused generate_expr/3 in wat_gen.ex
- Fix unused module_name variable in firebird.compile.ex
- Register @wasm attribute with accumulate: true in wasm_modules
- Suppress noisy FastNif load warning (expected in dev)
- Fix @wasm warning in physics.ex (missed in previous commit)
- Compile deps separately to avoid --warnings-as-errors on rustler
- Replace charlist literal with integer list for cross-version compat
Add WasmRunner.stream/4 which returns an Elixir Stream that:
- Loads the WASM instance lazily on first element consumed
- Calls the function one-at-a-time as elements are pulled
- Automatically stops the instance when the stream ends or halts
- Composes with all standard Stream/Enum functions

Unlike map/4 which eagerly evaluates everything into memory,
stream/4 enables lazy processing of large/unbounded input sets
with proper resource cleanup via Stream.resource/3.

Includes 16 tests covering: basic usage, early termination,
Stream.filter/map/chunk_every/take_while/with_index/zip composition,
Enum.take/find/reduce/count, cleanup guarantees, and equivalence
with map/4 for full consumption.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant