Skip to content

wasm-runner: add pipe/2 for chaining WASM function calls#4

Open
yevbar wants to merge 3 commits intomasterfrom
sleepy/wasm-runner-pipe
Open

wasm-runner: add pipe/2 for chaining WASM function calls#4
yevbar wants to merge 3 commits intomasterfrom
sleepy/wasm-runner-pipe

Conversation

@yevbar
Copy link
Copy Markdown
Contributor

@yevbar yevbar commented Feb 28, 2026

By Sleepy

Adds WasmRunner.pipe/3 and pipe!/3 that chain WASM function calls, feeding the output of each call as input to the next. The module is loaded once, all calls execute on a single instance, and cleanup is automatic.

Features:

  • Output of each call becomes first arg of the next by default
  • :pipe placeholder for explicit argument positioning
  • Works with precompiled modules, WASI auto-detection
  • 18 tests covering chaining, placeholders, errors, cleanup
  • Benchmark script comparing pipe vs separate run calls

Example:

{:ok, 42} = WasmRunner.pipe("math.wasm", [
  {:add, [5, 3]},           # => 8
  {:fibonacci, []},          # => fibonacci(8) = 21
  {:multiply, [:pipe, 2]}   # => multiply(21, 2) = 42
])

Note: test/firebird/test_case_test.exs has a pre-existing compilation error on master (CaseClauseError in TestCase macro expansion) — not related to this PR.

HDR Agent and others added 3 commits February 28, 2026 20:58
Adds the missing WasmRunner.run/2 and run!/2 functions for ergonomic
one-shot WASM execution with a keyword-list calling convention:

  {:ok, 8} = WasmRunner.run("math.wasm", add: [5, 3])
  {:ok, [8, 55]} = WasmRunner.run("math.wasm", add: [5, 3], fibonacci: [10])
  8 = WasmRunner.run!("math.wasm", add: [5, 3])

Features:
- Single call returns unwrapped value: {:ok, 8} not {:ok, [8]}
- Multiple calls return list: {:ok, [8, 55]}
- Options (wasi, cache) mixed into keyword list
- Works with precompiled modules for 53x speedup
- Auto WASI detection for Go modules
- Instance always cleaned up (even on error)

Performance characteristics (from benchmark):
- Cold run/2: ~2ms (dominated by WASM compilation)
- Precompiled run/2: ~40μs (53x faster)
- Pre-loaded call_single: ~15μs (call overhead only)
- WASM fibonacci(30) is 5x faster than pure Elixir

Includes:
- 22 tests covering single/multi calls, errors, cleanup, precompiled
- Benchmark: bench/wasm_runner_run.exs
- Performance docs in docs/PERFORMANCE_GUIDE.md
Adds Pool.call_many/2, call_many!/2, and call_many_unwrapped/2 for
executing multiple WASM function calls in a single checkout/checkin
cycle. This eliminates N-1 GenServer round-trips when batching calls.

Performance (fixtures/math.wasm, pool size 4):
- 5 calls:   1.27x faster than repeated Pool.call
- 20 calls:  1.18x faster
- 100 calls: 1.12x faster

Includes:
- 16 tests covering correctness, ordering, errors, concurrency
- Benchmark comparing call_many vs repeated call vs native Elixir
- Performance documentation in docs/POOL_CALL_MANY.md
Add WasmRunner.pipe/3 and pipe!/3 that chain WASM function calls,
feeding the output of each call as input to the next. The module is
loaded once, all calls execute on a single instance, and cleanup is
automatic.

Features:
- Output of each call becomes first arg of the next by default
- :pipe placeholder for explicit argument positioning
- Works with precompiled modules, WASI auto-detection
- Includes 18 tests covering chaining, placeholders, errors, cleanup
- Benchmark script comparing pipe vs separate run calls

Example:
  {:ok, 42} = WasmRunner.pipe("math.wasm", [
    {:add, [5, 3]},           # => 8
    {:fibonacci, []},          # => fibonacci(8) = 21
    {:multiply, [:pipe, 2]}    # => multiply(21, 2) = 42
  ])
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