Skip to content

Technical Deep Dives

Model sourcing, backend semantics, browser compatibility


CPU (pure JS) vs WASM — genuinely different in TF.js

TensorFlow.js has two CPU-targeting backends that are not aliases:

Backend Execution Performance
CPU Pure JavaScript TF ops (interpreted) Slowest — no compilation, no threading
WASM Compiled C++ TF ops via WebAssembly + SharedArrayBuffer threads Significantly faster — multi-threaded C++ runtime

This is one of the most interesting benchmark dimensions: the perf delta between interpreted JS and compiled WASM with threading. ONNX Runtime Web does not offer a pure-JS CPU path — its cpu option is an alias for wasm.


WebNN — emerging NPU backend (ORT only)

Discovered during review of the ONNX Runtime Web official docs: ORT supports webnn as an execution provider, usable for both GPU and CPU processing via deviceType.

Browser Platform WebNN Backend
Chrome 113+ / Edge Windows DirectML (GPU via MLDeviceType.gpu)
Chrome / Edge macOS CoreML / ANE (Neural Engine via MLDeviceType.cpu)
Chrome / Edge Linux TBD — limited support
Safari / Firefox All Not supported

WebNN routes inference through the OS-level ML stack — DirectML on Windows, CoreML/ANE on macOS. This is conceptually closer to an NPU backend than a traditional GPU backend, since it uses dedicated ML accelerators where available. Browser support is limited but growing. We include it in the backend matrix as ORT-only with a navigator.ml feature check gate.

Validated in benchy (Aug 2026)

WebNN works unflagged in Chromium-based browsers on supported hardware: onnx webnn completed end-to-end on Edge stable/Win11 (median 59.85 ms, internal backend truth-reported webnn); Firefox → skipped/webnn-unavailable (Detect & Report). Evidence: research/validation-gate-benchy.md. WebNN stays excluded from the primary measured matrix for cross-browser comparability (no non-Chromium browser ships it).


Why include Transformers.js when it wraps ORT?

Transformers.js v4 uses ONNX Runtime Web as its inference engine. Benchmarking both could be seen as comparing ORT against itself. However, Transformers.js adds meaningful differences:

  • API level: Pipeline abstraction (pipeline("image-classification", model)) vs raw session+tensor management in bare ORT
  • Ecosystem: HuggingFace model hub integration, auto-download, auto-tokenization
  • Model variants: Uses onnx-community quantized models which may differ from the raw ONNX models we use with bare ORT
  • Developer experience: Represents the "ease of use" end of the spectrum — relevant to the thesis Integration criterion

The pipeline overhead for a single image classification forward pass is negligible, so performance should be nearly identical to bare ORT. Any difference would come from model quantization differences, not framework overhead.

Terminology

In the thesis, Transformers.js is classified as a framework (high-level API), not a runtime (low-level engine). The comparison includes both runtimes and frameworks to span the abstraction spectrum.


ONNX model sourcing: HuggingFace CDN

The ONNX Runtime Web adapter was originally broken — ONNX_MODEL_URL = null with the comment "GitHub LFS doesn't work via CDN." GitHub serves LFS-tracked binary files as pointer files (~130 bytes containing an OID hash) rather than the actual model weights when accessed via jsDelivr or raw URLs.

Resolution: ONNX models are loaded directly from HuggingFace's /resolve/main/ CDN path — no authentication required:

https://huggingface.co/onnxmodelzoo/mobilenetv2-12/resolve/main/mobilenetv2-12.onnx

This serves the actual binary file (not LFS pointers) with proper CORS headers. The ONNX Model Zoo GitHub repo (github.com/onnx/models) discontinued LFS downloads in July 2025; HuggingFace is the official successor at huggingface.co/onnxmodelzoo with 2,326+ models.

The adapter reads model URLs from the MODEL_REGISTRY in pipeline.js rather than hardcoding them.


MODEL_REGISTRY — centralizing model distribution

Each adapter previously hardcoded model URLs from different sources (jsDelivr, HuggingFace, Google Storage). The MODEL_REGISTRY in pipeline.js centralizes:

  • Model metadata: name, description, input size
  • Per-runtime CDN URLs: one entry per (model, runtime) pair pointing to the appropriate CDN
  • Runtime filtering: the UI greys out runtimes that don't have a model available

Three CDN sources cover all current needs: HuggingFace Hub (for ORT .onnx models), TF Hub / jsDelivr (for TF.js and LiteRT.js .tflite models), and Google Storage (for MediaPipe pre-optimized models).


Browser compatibility: SharedArrayBuffer & COOP/COEP

ONNX Runtime Web's WASM backend and MediaPipe Tasks require SharedArrayBuffer, which needs Cross-Origin-Opener-Policy: same-origin and Cross-Origin-Embedder-Policy: require-corp HTTP headers. Without them, WASM backends cannot use multi-threading.

Non-technical users

Opening index.html via file:// will NOT work — a server with COOP/COEP headers is required. See ml-browser-check for server setup details.