v8.50.0
YaneuraOu shogi engine — WebAssembly builds.
What's new in this release: Node.js-targeted packages (@ultemica/yaneuraou-wasm-node-*) join the
browser and Cloudflare Workers builds, so the engine can be driven from a plain
Node process with no browser involved.
kp256/mate/halfkp256/halfkp768, all multi-threaded via
node:worker_threads.- Built with emscripten 3.1.43 — the only toolchain currently verified to
drive a pthread-backed YaneuraOu cleanly under Node (newer emscriptens stall,
seedocs/wasm_client_usage.mdfor the matrix). - Drop-in
createEngine()loader: zero boilerplate on the consumer side. The
package wraps thenode:worker_threadsplumbing,Workerpolyfill,
web-globals shim, andnoInitialRun+callMainbootstrap internally. - Verified on Node 26 with KP256 + suishopetite — depth 24 in ~3.4 s at
threads=1(~0.84 M nps), ~6.8 s atthreads=4(~3.32 M nps, roughly linear).
Note (added later): this release originally shipped twenty packages,
including Material / Mobility engines and HumanLike (-hlsl) variants of each
engine. Those assets have since been removed to keep the published set to the
ten variants that are useful for play and analysis; their sources remain in the
repository. The engine binaries for the remaining ten are unchanged from the
original 8.50.0 publish.
Each archive contains the package's package.json (version bumped to this release), README.md, SPEC.md, the TypeScript loader (dist/index.js, dist/index.d.ts), and the engine bundle (dist/yaneuraou.js, dist/yaneuraou.wasm, .wasm.br). Node variants additionally ship dist/yaneuraou.worker.js (the emscripten 3.1.43 classic pthread worker) and dist/worker_shim.{js,d.ts} (the worker_threads-side glue the loader uses to bridge .worker.js into a fake web-worker scope).
Packages
Browser / Cloudflare Workers
| Package | Engine | Eval data | Threading | Initial / Max memory | Target |
|---|---|---|---|---|---|
@ultemica/yaneuraou-wasm-kp256-cfworkers |
NNUE KP256 (Suishopetite) | external (~873 KB) | single-thread | 64 MB / 128 MB | Cloudflare Workers, edge runtimes |
@ultemica/yaneuraou-wasm-mate-cfworkers |
Mate (DfPn) | none | single-thread | 64 MB / 128 MB | Cloudflare Workers, edge runtimes |
@ultemica/yaneuraou-wasm-pthread-kp256 |
NNUE KP256 (Suishopetite) | external (~873 KB) | pthread | 128 MB / 1 GB | Browser (COOP/COEP required) |
@ultemica/yaneuraou-wasm-mate-pthread |
Mate (DfPn) | none | pthread | 128 MB / 1 GB | Browser (COOP/COEP required) |
@ultemica/yaneuraou-wasm-pthread-halfkp256 |
NNUE HalfKP_256x2_32_32 (Suisho5) | external (~62 MB) | pthread | 256 MB / 2 GB | Browser (COOP/COEP required) |
@ultemica/yaneuraou-wasm-pthread-halfkp768 |
NNUE HalfKP_768x2_16_64 (AobaNNUE) | external (~184 MB) | pthread | 256 MB / 2 GB | Browser (COOP/COEP required) |
Cloudflare Workers cannot host pthread builds — use the cfworkers variant there. HalfKP cfworkers variant does not exist (eval exceeds Workers memory budget).
Node.js variants
Four packages built with EM_ENVIRONMENT=node, EM_PTHREAD=1, and EM_EXPORTED_RUNTIME_METHODS=['FS','ccall','callMain']. Pinned to emscripten 3.1.43 — the only toolchain currently verified to drive a multi-threaded YaneuraOu correctly under Node (3.1.44–3.1.73 stall on ESM workers, 3.1.74+ stall on INCOMING_MODULE_JS_API; both unresolved). See docs/wasm_client_usage.md for the full compatibility matrix.
| Package | Engine | Eval data | Threading | Initial / Max memory |
|---|---|---|---|---|
@ultemica/yaneuraou-wasm-node-kp256 |
NNUE KP256 (Suishopetite) | external (~873 KB) | pthread | 128 MB / 1 GB |
@ultemica/yaneuraou-wasm-node-mate |
Mate (DfPn) | none | pthread | 128 MB / 1 GB |
@ultemica/yaneuraou-wasm-node-halfkp256 |
NNUE HalfKP_256x2_32_32 (Suisho5) | external (~62 MB) | pthread | 256 MB / 2 GB |
@ultemica/yaneuraou-wasm-node-halfkp768 |
NNUE HalfKP_768x2_16_64 (AobaNNUE) | external (~184 MB) | pthread | 256 MB / 2 GB |
Quickstart (Node 18+):
import fs from "node:fs/promises";
import { createRequire } from "node:module";
import { createEngine } from "@ultemica/yaneuraou-wasm-node-kp256";
import YaneuraOuFactory from "@ultemica/yaneuraou-wasm-node-kp256/engine";
const require = createRequire(import.meta.url);
const wasmPath = require.resolve("@ultemica/yaneuraou-wasm-node-kp256/wasm");
const enginePath = require.resolve("@ultemica/yaneuraou-wasm-node-kp256/engine");
const wasmBinary = await fs.readFile(wasmPath);
const evalBin = await fs.readFile("./eval/nn.bin"); // suishopetite for KP256
const engine = await createEngine({
factory: YaneuraOuFactory,
enginePath,
wasmBinary,
evalBin,
threads: 4,
usiHash: 64,
});
const result = await engine.eval({
sfen: "lnsgkgsnl/1r5b1/ppppppppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGSNL b - 1",
byoyomi: 2_000,
});
console.log(result.bestmove, result.score); // -> "7g7f", { kind: "cp", value: ... }
engine.dispose();Requires Node.js 18 or later. Browsers cannot load these binaries (built with
EM_ENVIRONMENT=node, notweb,worker); use thepthread-*packages there. Cloudflare Workers / V8 Isolate environments can't host pthread builds at all; use the*-cfworkerspackages there.
Performance — how close to native?
WASM is not the slow option. Measured on one machine with the same eval and the
same search parameters, WASM reaches about 92% of a native SIMD build.
| Build | nps | vs native NEON |
|---|---|---|
| native clang-14 (NEON) | 764k | 102% |
| native gcc (NEON) | 748k | 100% |
| wasm32 pthread | 691k | 92% |
| wasm32 (no SIMD) | 585k | 78% |
| native clang-14 (scalar) | 320k | 43% |
| native gcc (scalar) | 203k | 27% |
Threads=1 / go nodes 1000000 / KP256 + suishopetite / median of 3 runs.
Absolute numbers are machine-dependent — only the ratios carry over.
- WASM SIMD is doing real work. Turning it off drops 691k to 585k (-15%).
WASM still beats both native scalar builds by more than 2x. - Threads scale. On Node, 1 to 4 threads goes 686k to 2,916k (4.25x) —
superlinear thanks to the shared transposition table. - Browser and Node are within noise. 99% at 1 thread, 92% at 4 threads;
SharedArrayBuffersynchronisation costs the browser a little.
Search results are bit-identical across every WASM variant (32/64-bit,
SIMD on/off, browser/Node/edge) down to the node count, so switching runtimes
does not change what the engine plays.
Full conditions and raw data: docs/reports/2026-07-28_wasm_v96x_performance.md.
Required: NNUE eval file (NNUE builds only)
WASM bundle には評価関数を内蔵していないので、別途 nn.bin を取得して FS.writeFile で MEMFS に書いて EvalDir USI option で読み込ませる。
| Eval | Engine | Size | URL |
|---|---|---|---|
| suisho5 nn.bin | HalfKP_256x2_32_32 | ~62 MB | https://github.com/mizar/YaneuraOu/releases/download/resource/suisho5_20211123.halfkp.nnue.cpp.gz |
| AobaNNUE nn.bin | HalfKP_768x2_16_64 | ~184 MB | https://github.com/yssaya/AobaNNUE/releases |
| suishopetite nn.bin | KP256 | ~873 KB | https://github.com/mizar/YaneuraOu/releases/download/resource/suishopetite_20211123.k_p.nnue.cpp.gz |
suisho5 / suishopetite は embedded C++ array 形式の
.cpp.gz。script/eval_bin_to_cpp_literal.pyの逆変換で.binに戻す。AobaNNUE は素のnn.binがそのまま配布されている。
KP256 / HalfKP_256x2_32_32 / HalfKP_768x2_16_64 の eval はそれぞれ互換性なし。Mate engine は eval 不要。HalfKP eval (62 MB) は cfworkers の 128 MB heap で OOM になるため pthread variant でのみ使える。
Optional: opening book
BookDir / BookFile USI option で読み込ませる。
| Book | 局面数 | Size | URL |
|---|---|---|---|
| 100T-shock | ~40,000 | 4.7 MB | https://github.com/yaneurao/YaneuraOu/releases/download/BOOK-100T-Shock/100T-shock-book.zip |
| 700T-shock | ~400,000 | 32 MB | https://github.com/yaneurao/YaneuraOu/releases/download/BOOK-700T-Shock/700T-shock-book.zip |
| 新ペタショック 233万 | ~2,330,000 | 76 MB (.7z) | https://github.com/yaneurao/YaneuraOu/releases/download/new_petabook233/new_petabook_20250505c.7z |
700T-shock (32 MB) は cfworkers の 128 MB heap だと OOM。cfworkers で book を使う場合は 100T-shock まで。petabook は pthread variant でも heap 圧迫するので注意。