Skip to content

Benchmarks

Benchmarks of ruNNtime against the alternatives. Same model, same input, same browser, one engine at a time: ruNNtime zoo, ruNNtime through the transformers.js plugin, and stock transformers.js on ONNX Runtime, all on WebGPU. All tests were performed on an Apple M2 Pro.

Moonshine on 500 utterances of LibriSpeech test-clean, 66 minutes of speech. ruNNtime runs the f16 weights in half precision, its default. transformers.js runs the fp32 and q4 ONNX exports.

Seconds of audio transcribed per second. Higher is better.

  • ruNNtime tiny89×
  • ruNNtime tiny, tjs plugin92×
  • transformers.js tiny fp3233×
  • transformers.js tiny q434×
  • ruNNtime base52×
  • ruNNtime base, tjs plugin53×
  • transformers.js base fp3224×
  • transformers.js base q426×
  • ruNNtime streaming tiny87×

Decode time per generated token. Lower is better.

  • ruNNtime tiny2.8 ms
  • ruNNtime tiny, tjs plugin2.7 ms
  • transformers.js tiny fp327.2 ms
  • transformers.js tiny q46.9 ms
  • ruNNtime base4.9 ms
  • ruNNtime base, tjs plugin4.8 ms
  • transformers.js base fp329.6 ms
  • transformers.js base q49.0 ms
  • ruNNtime streaming tiny2.9 ms
ModelEnginePrecision× realtimems per token66 min of audio in
tinyruNNtimef16892.843 s
tinyruNNtime, tjs pluginf16922.742 s
tinytransformers.jsfp32337.2120 s
tinytransformers.jsq4346.9118 s
baseruNNtimef16524.975 s
baseruNNtime, tjs pluginf16534.873 s
basetransformers.jsfp32249.6167 s
basetransformers.jsq4269.0157 s
streaming tinyruNNtimef16872.948 s

all-MiniLM-L6-v2 on 1000 Wikipedia paragraphs, 22 to 629 words each, in batches of 1, 8 and 32 paragraphs per call. ruNNtime runs the f16 weights in half precision, its default. transformers.js runs the fp32 ONNX export, its WebGPU default, plus the fp16 and q4 exports.

Higher is better.

  • ruNNtime351/s
  • ruNNtime, tjs plugin190/s
  • transformers.js fp3281/s
  • transformers.js fp16117/s
  • transformers.js q491/s
  • ruNNtime303/s
  • ruNNtime, tjs plugin191/s
  • transformers.js fp32117/s
  • transformers.js fp16156/s
  • transformers.js q4120/s

Milliseconds per paragraph.

EnginePrecisionBatch 1Batch 8Batch 32
ruNNtimef167.03.12.7
ruNNtimef326.24.14.5
ruNNtime, tjs pluginf169.14.85.2
transformers.jsfp327.77.611.3
transformers.jsfp166.65.98.3
transformers.jsq47.77.110.9

MobileNetV4 on 500 COCO photos, one photo per call, pixels in to class names out. ruNNtime runs the f16 weights, its only precision. transformers.js runs the fp32 ONNX export, its WebGPU default, plus the fp16 and q4 exports. Through the plugin, ruNNtime keeps transformers.js’s image preprocessing, which is most of that row’s time.

Higher is better.

  • ruNNtime407 fps
  • ruNNtime, tjs plugin103 fps
  • transformers.js fp3287 fps
  • transformers.js fp1686 fps
  • transformers.js q483 fps
EnginePrecisionms per imageFPS
ruNNtimef162.4407
ruNNtime, tjs pluginf169.4103
transformers.jsfp3210.987
transformers.jsfp1611.286
transformers.jsq411.783

DepthART on 500 COCO photos, one photo per call, pixels in to a depth map out. ruNNtime runs the f16 weights, its only precision. Through the plugin, ruNNtime runs DepthART with transformers.js’s image preprocessing, which is most of that row’s time.

Higher is better.

  • ruNNtime51.0 fps
  • ruNNtime, tjs plugin20.0 fps
EnginePrecisionms per imageFPS
ruNNtimef1619.351
ruNNtime, tjs pluginf1650.120

YOLO26 on 500 COCO photos, one photo per call, pixels in to boxes out, in the n, s and m sizes. ruNNtime runs the f16 weights, its only precision. transformers.js runs the ONNX export of the same model in fp32, its WebGPU default, plus the fp16 and q4 exports. Through the plugin, ruNNtime keeps transformers.js’s image preprocessing.

Higher is better.

  • ruNNtime n61.0 fps
  • ruNNtime n, tjs plugin27.1 fps
  • transformers.js n fp3222.8 fps
  • transformers.js n fp1624.0 fps
  • transformers.js n q422.2 fps
  • ruNNtime s32.1 fps
  • ruNNtime s, tjs plugin20.0 fps
  • transformers.js s fp3217.4 fps
  • transformers.js s fp1619.4 fps
  • transformers.js s q417.3 fps
  • ruNNtime m13.6 fps
  • ruNNtime m, tjs plugin11.1 fps
  • transformers.js m fp3211.2 fps
  • transformers.js m fp1613.7 fps
  • transformers.js m q411.3 fps
ModelEnginePrecisionms per imageFPS
nruNNtimef1616.361.0
nruNNtime, tjs pluginf1634.527.1
ntransformers.jsfp3242.522.8
ntransformers.jsfp1637.924.0
ntransformers.jsq446.422.2
sruNNtimef1631.032.1
sruNNtime, tjs pluginf1648.520.0
stransformers.jsfp3256.617.4
stransformers.jsfp1650.619.4
stransformers.jsq457.717.3
mruNNtimef1673.013.6
mruNNtime, tjs pluginf1689.611.1
mtransformers.jsfp3288.611.2
mtransformers.jsfp1672.413.7
mtransformers.jsq488.611.3

YOLO26 pose and YOLO26 segment on the same 500 COCO photos, one photo per call, in the n, s and m sizes. ruNNtime runs the f16 weights, its only precision. transformers.js has no pipeline for these models, so there is no row to compare with.

Higher is better.

  • ruNNtime n53.6 fps
  • ruNNtime s29.3 fps
  • ruNNtime m12.8 fps

Higher is better.

  • ruNNtime n43.0 fps
  • ruNNtime s20.1 fps
  • ruNNtime m7.2 fps

Pose:

ModelEnginePrecisionms per imageFPS
nruNNtimef1618.553.6
sruNNtimef1634.029.3
mruNNtimef1677.912.8

Instance segmentation:

ModelEnginePrecisionms per imageFPS
nruNNtimef1623.043.0
sruNNtimef1649.320.1
mruNNtimef161387.2

Privacy filter on 300 short messages with personal data, 9 to 76 words each, one message per call, text in to labelled spans out. ruNNtime runs the int8 weights, its only precision. transformers.js runs the ONNX exports of the same model in q4 and q4f16. Its q8 export finds almost none of the spans on WebGPU, so it is left out. Through the plugin, ruNNtime keeps transformers.js’s tokenizer.

Higher is better.

  • ruNNtime32.3/s
  • ruNNtime, tjs plugin32.2/s
  • transformers.js q411.7/s
  • transformers.js q4f1615.0/s
EnginePrecisionms per textTexts per second
ruNNtimeint831.832.3
ruNNtime, tjs pluginint831.832.2
transformers.jsq485.911.7
transformers.jsq4f1667.515.0
  • Machine: MacBook Pro, Apple M2 Pro, 16 GB, Chromium 148, WebGPU on Metal.
  • Setup: ruNNtime as in Getting started, with subgroups and shader-f16, the hosted weights. transformers.js 4.2.0, device: 'webgpu', the onnx-community, Xenova and openai ONNX exports at the row’s dtype.
  • Timing: one engine loaded at a time, every input runs once untimed first. Reported numbers are medians.
  • Speech to text: the first 500 utterances of LibriSpeech test-clean, 65.8 minutes, 1.4 to 31.6 s per clip, 16 kHz mono, the same samples for every engine. Each clip is timed once, samples in to text out. × realtime is audio seconds over seconds taken, median over the 500 clips. ms per token is decode time over tokens produced, median over clips. Every transcript is checked against the reference.
  • Text embedding: the 1000 distinct paragraphs of SQuAD v1.1 dev, Wikipedia text, capped at 512 tokens, the same for every engine. Two passes per batch size, text in to unit-length vectors out. Paragraphs per second is the whole set over the time it took. ms per paragraph is the median call time over the batch size. Every vector is checked against the ruNNtime f32 output.
  • Vision tasks: image classification, depth estimation, object detection, pose and instance segmentation run on the first 500 COCO val2017 photos under a license that allows reuse, 69k to 410k pixels each, decoded once, the same for every engine. Four passes, RGBA pixels in, the task’s result out at each engine’s default threshold. FPS is the whole set over the time it took. ms per image is the median call time. Every result is checked against ruNNtime’s.
  • Privacy filter: 300 English messages, 9 to 76 words, with names, emails, phones, addresses, dates, URLs, account numbers and secrets, the same for every engine. Four passes, text in to labelled spans out. Texts per second is the whole set over the time it took. ms per text is the median call time. Every span set is checked against ruNNtime’s.