Suggestion: Rust runtime traps on wasm32 (Instant::now), one-line fix

#1
by nielsdejong - opened

Hi, I compiled the Rust runtime to wasm32-unknown-unknown to run
TinyDecide in a browser. It needs one change first.

The bug

rust/src/engine.rs:4 imports std::time::Instant, and answer_with()
opens with Instant::now(). That target has no monotonic clock in std,
so it compiles and then traps with RuntimeError: unreachable. Every call
to answer() fails. The value only fills the diagnostic Response.ms
(engine.rs:533).

The fix

Two lines. In rust/src/engine.rs, replace line 4:

use std::time::Instant;

with:

use web_time::Instant;

And in rust/Cargo.toml, add one entry to [dependencies] after line 17:

web-time = "1"

That's the whole change. web-time
maps Instant to performance.now() on wasm32 and re-exports
std::time::Instant unchanged on every other target, so native behaviour
is identical. Your cargo test --release passes with it applied, on
both builds.

What it gets you

A 408 KB build that passes your conformance/ fixture (max Δ 6.521e-7 on
S768, 7.175e-7 on full, 0 pick/span mismatches) and answers a
4-question, 67-token request in 82.8 ms against 646.8 ms for
tinydecide.js: 7.8× faster, identical answers
. Native is ~30 ms.

Most of that is -C target-feature=+simd128, worth 2.9× on its own and
changing no results. Your dot already has 16 independent accumulators
"so the loop vectorises", but on wasm32 LLVM has no vector target unless
the feature is on. Worth a line in rust/README.md.

Thanks for shipping the conformance fixtures, they made checking a new
engine straightforward.

Thanks, good catch
I fixed it a bit different. web-time pulls in wasm-bindgen, so the module would no longer run in hosts without JS glue. Instead the timer is skipped on that target. Response.ms is 0 there, and the crate builds with no imports and no extra dependencies.
Thanks again for your simd128 tip (really 2.6x faster here, with same output)

TheREZOR changed discussion status to closed

Sign up or log in to comment