Repository navigation
Breaking
getStatus()returns{ running, tick, linkCount, componentCount }.runningistruefrom
therunAsync()call until its promise settles. It replacesstate, and theSimStatetype and
Node enum are gone.speedis gone too: for a ticks/s readout, sampletickagainst a clock.
During a run it is at most one batch behind: about 1 ms on Node, 5 ms in WASM.linkCount()andcomponentCount()are gone from both bindings: read them from
getStatus().- On Node, a delta snapshot's
idsis aUint32Array, like itsinvalid, instead of a
Bufferof little-endianu32s. - In WASM,
runAsync()rejects while another run on the same simulation is in progress and not
stopped, andrun()throws then, as on Node. Both used to run, interleaved between batches. - Both bindings read boards and run configs with the same rules and messages:
- A field that is
undefinedis absent, andnullis refused. WASM used to read anull
field or bound as absent. - Numbers must be exact non-negative integers where the board holds a
u32or a byte. Node used
to truncate them, so atypeof 1.5 built a NOT and aperiodof 2.7 became 2. - Unknown fields are ignored.
- A run config must be an object. Node used to start an unbounded run for
runAsync(5). A
malformed config throws fromrunAsync()in WASM too, instead of rejecting its promise. - Fields are checked in order, component by component, so a board with several mistakes names
the same one in both.
- A field that is
- In WASM,
link(id)throws for an id past the last link, as on Node. It used to returnfalse. - In Rust:
Simulation::runreturns nothing, andSimState,Simulation::state,Simulation::stopand
thestateandspeedfields ofStatusare gone.read_state(comp, offset, len)returns the bytes, andread_records(comp, since, max)returns
them inRecordswith their ticks, instead of filling buffers;SimError::RecordTicksis
gone.InputRequestbuilds an ownedsubmit_inputrequest;inputs()lists theUserInputs.Board,Simulation::newandStateLayout::ofare no longer public: build a simulation
withSimulation::from_descriptor, and read a layout withSimulation::state_layout.SnapshotInfodropschanged: a delta's changed links aresnapshot_ids().
Performance
- In browsers, the WASM
runAsync()no longer idles 4 ms between batches: it yields through a
MessageChannelinstead of a nestedsetTimeout(0), which browsers clamp to 4 ms. An unbounded
run now ticks as fast as a blockingrun(), about 1.5× its previous speed on a board that
changes every tick. Under Node it yields withsetImmediate, withoutsetTimeout's 1 ms.
Fixed
- A run with an
msbound ends within about a tick of it on any board, in the CLI and both
bindings. The engine used to read the clock only after its first 1 021 ticks, and the Node addon
every 4 093, so on a board at 5 000 ticks/s,run({ ms: 5 })took 0.2 s in WASM and 0.6 s on
Node. runAsync()works in batches of about 5 ms in WASM and 1 ms on Node on any board, sostop(),
snapshots and messages wait at most that long. On a board at 5 000 ticks/s, a WASM batch used
to hold the thread for 0.2 s and a Node snapshot waited up to 0.9 s. On Node,stop()now takes
effect at the end of a batch rather than at the next tick. Batch lengths vary by a tick, so state
read between batches reaches every phase of a periodic signal, even on a board slow enough for a
batch to be a few ticks.- During a WASM
runAsync(),getStatus()reports the run, as on Node. It used to report
Stopped. On Node, it reports the run from therunAsync()call until the promise settles; it
used to report it only once the worker had picked the run up, and could stop before the promise
settled. readRecordsallocates for the records it returns. It used to allocate the recorder's full
capacity on every call, about 12 MiB for a large recorder with ticks; in WASM that could grow
memory and detach every outstanding snapshot view.- Freeing a WASM simulation (
destroy(),free()or garbage collection) during arunAsync()
ends the run. It used to keep ticking forever, and kept a Node process alive. - A
runAsync()orrun()called straight afterstop(), before the stopped run's promise has
settled, starts. In WASM, the newrunAsync()used to revive the stopped run, which then never
ended. On Node, it was rarely rejected as a run already in progress.
Full Changelog: v0.6.0...v0.7.0