Skip to content

Resident buffers

Examples assume an initialized engine; see getting started.

Reuse memory within a scope

Use a scope to upload once, reuse allocations across operations, and copy the result back once. This avoids intermediate copies between JS and Wasm memory.

ts
const processed = engine.scope(scope => {
  const left = scope.f32.from(new Float32Array([0.2, 0.4, 0.6]))
  const right = scope.f32.from(new Float32Array([0.1, 0.3, 0.5]))
  const output = scope.f32.alloc(left.length)

  scope.f32.add(left, right, { out: output })
  scope.f32.mul(output, 0.5, { out: output })
  scope.f32.clamp(output, 0, 1, { out: output })
  return output.toArray()
})

Each operation remains a separate traversal. Scope allocations are released in a finally block, including when your callback throws. Returning a buffer does not extend its lifetime. Promise/thenable results are rejected; use a persistent arena when the lifetime must span frames or asynchronous application code.

Keep buffers across calls

ts
const arena = engine.createArena()
try {
  const samples = arena.f32.alloc(1024) // initialized to zero
  const output = arena.f32.alloc(1024)

  samples.set(new Float32Array(1024).fill(0.25))
  arena.f32.mul(samples, 2, { out: output })
  const frame = output.toArray()
  // Reuse samples and output on the next frame.
} finally {
  arena.dispose()
}

arena.f32 has the same operations, using F32Buffer instead of Float32Array. from and set always copy; toArray always returns an independent copy. There are no exposed pointers or persistent Wasm memory views.

Ownership and output rules

Memory ruleBehavior
Exact input/output aliasSupported, including two views of the same exact region
Partial output/input overlapRejected before writing
Read-only inputs overlapSupported
Array or buffer lengths differRangeError
Different engines' buffers mixedRejected
Different live arenas of the same engineSupported
Access after arena/engine disposalRejected; disposal itself is idempotent
Wasm memory growsExisting buffer handles remain valid
Shared, resizable or detached backing memoryRejected
TypedArrays from a different JS realmRejected; copy into this realm first

Copying and reclamation

Ordinary TypedArray calls to native borrow the existing memory synchronously; provided outputs are written directly. Ordinary TypedArray calls to Wasm copy inputs into scratch allocations and copy results back. Resident allocations avoid those per-operation copies. Arena disposal releases its allocations for reuse; Wasm linear memory does not shrink until the engine is disposed and collected. Retaining a disposed buffer does not retain its allocation.

Released under the MIT License.