Browser-side background removal benchmarks
Koutuxia's free background removal downloads the model into the visitor's browser and runs it there, so images are not uploaded to our server: BiRefNet_lite by default, or the full BiRefNet with a Swin-Large backbone when “Maximum quality” is ticked — both use a fixed 1024² input and both run on WASM only. The trade-off is that speed is decided entirely by that machine: whether WASM can use several threads, how fast the CPU is, and how large the image is all change the result. So this page gives a distribution rather than a single number — measured on devices in actual use and split by execution backend and device class, not a marketing figure from one fast machine.
Telemetry from real devices
Last 90 days, 476 samples, most recent 2026-10-03.
Combinations with fewer than 30 samples are still listed, greyed out — hiding them would leave readers unable to tell "no data here" from "we dropped this one".
| Phase | Backend | Device | CPU cores | Samples | p50 | p95 | of which inference p50 |
|---|---|---|---|---|---|---|---|
| Model first download | wasm | Desktop | 1-3 | 1(too few samples) | 17.93 s | 17.93 s | — |
| Model first download | wasm | Desktop | 12+ | 24(too few samples) | 18.29 s | 330.48 s | — |
| Model first download | wasm | Desktop | 12+ | 2(too few samples) | 46.65 s | 82.13 s | — |
| Model first download | wasm | Desktop | 4-7 | 4(too few samples) | 14.87 s | 76.48 s | — |
| Model first download | wasm | Desktop | 8-11 | 34 | 4.83 s | 7.71 s | — |
| Model first download | wasm | Desktop | 8-11 | 1(too few samples) | 5.76 s | 5.76 s | — |
| Model first download | wasm | Mobile | 8-11 | 3(too few samples) | 5.92 s | 113.87 s | — |
| Model first download | wasm-st | Desktop | 8-11 | 1(too few samples) | 14.44 s | 14.44 s | — |
| Model first download | wasm-st | Mobile | 8-11 | 1(too few samples) | 68.15 s | 68.15 s | — |
| Model first download | webgpu | Desktop | 12+ | 1(too few samples) | 27.18 s | 27.18 s | — |
| Model first download | webgpu | Desktop | 4-7 | 1(too few samples) | 23.15 s | 23.15 s | — |
| Model first download | webgpu | Desktop | 8-11 | 1(too few samples) | 5.57 s | 5.57 s | — |
| Model first download | webgpu | Mobile | 4-7 | 1(too few samples) | 14.59 s | 14.59 s | — |
| Model first download | webgpu | Mobile | 8-11 | 3(too few samples) | 6.14 s | 14.69 s | — |
| Model cache hit | wasm | Desktop | 1-3 | 10(too few samples) | 56 ms | 147 ms | — |
| Model cache hit | wasm | Desktop | 12+ | 23(too few samples) | 59 ms | 234 ms | — |
| Model cache hit | wasm | Desktop | 4-7 | 7(too few samples) | 160 ms | 1.76 s | — |
| Model cache hit | wasm | Desktop | 8-11 | 41 | 23 ms | 136 ms | — |
| Model cache hit | wasm | Mobile | 8-11 | 7(too few samples) | 84 ms | 365 ms | — |
| Model cache hit | wasm-st | Mobile | 4-7 | 1(too few samples) | 30 ms | 30 ms | — |
| Model cache hit | wasm-st | Mobile | 8-11 | 1(too few samples) | 294 ms | 294 ms | — |
| Model cache hit | webgpu | Desktop | 12+ | 1(too few samples) | 101 ms | 101 ms | — |
| Model cache hit | webgpu | Desktop | 4-7 | 2(too few samples) | 366 ms | 378 ms | — |
| Model cache hit | webgpu | Mobile | 8-11 | 1(too few samples) | 198 ms | 198 ms | — |
| Runtime load | wasm | Desktop | 1-3 | 11(too few samples) | 2.29 s | 4.19 s | — |
| Runtime load | wasm | Desktop | 12+ | 47 | 2.27 s | 5.33 s | — |
| Runtime load | wasm | Desktop | 12+ | 2(too few samples) | 4.37 s | 5.35 s | — |
| Runtime load | wasm | Desktop | 4-7 | 11(too few samples) | 6.54 s | 10.38 s | — |
| Runtime load | wasm | Desktop | 8-11 | 75 | 2.36 s | 6.55 s | — |
| Runtime load | wasm | Desktop | 8-11 | 1(too few samples) | 1.57 s | 1.57 s | — |
| Runtime load | wasm | Mobile | 8-11 | 10(too few samples) | 1.86 s | 40.45 s | — |
| Runtime load | wasm-st | Desktop | 8-11 | 1(too few samples) | 7.44 s | 7.44 s | — |
| Runtime load | wasm-st | Mobile | 4-7 | 1(too few samples) | 4.44 s | 4.44 s | — |
| Runtime load | wasm-st | Mobile | 8-11 | 2(too few samples) | 5.75 s | 5.85 s | — |
| Runtime load | webgpu | Desktop | 12+ | 2(too few samples) | 6.90 s | 9.03 s | — |
| Runtime load | webgpu | Desktop | 4-7 | 3(too few samples) | 8.54 s | 9.56 s | — |
| Runtime load | webgpu | Desktop | 8-11 | 1(too few samples) | 9.27 s | 9.27 s | — |
| Runtime load | webgpu | Mobile | 4-7 | 1(too few samples) | 11.30 s | 11.30 s | — |
| Runtime load | webgpu | Mobile | 8-11 | 4(too few samples) | 13.83 s | 31.89 s | — |
| First cutout | wasm | Desktop | 1-3 | 6(too few samples) | 5.17 s | 6.39 s | 4.55 s |
| First cutout | wasm | Desktop | 12+ | 32 | 3.35 s | 7.44 s | 2.27 s |
| First cutout | wasm | Desktop | 12+ | 1(too few samples) | 6.11 s | 6.11 s | 5.65 s |
| First cutout | wasm | Desktop | 4-7 | 2(too few samples) | 12.85 s | 14.80 s | 12.17 s |
| First cutout | wasm | Desktop | 8-11 | 71 | 2.12 s | 10.30 s | 1.74 s |
| First cutout | wasm | Mobile | 8-11 | 5(too few samples) | 4.12 s | 5.41 s | 2.75 s |
| First cutout | wasm-st | Mobile | 8-11 | 2(too few samples) | 44.06 s | 44.86 s | 43.32 s |
| First cutout | webgpu | Desktop | 12+ | 2(too few samples) | 4.67 s | 7.37 s | 4.47 s |
| First cutout | webgpu | Desktop | 4-7 | 3(too few samples) | 14.27 s | 17.21 s | 12.87 s |
| First cutout | webgpu | Desktop | 8-11 | 1(too few samples) | 4.76 s | 4.76 s | 3.47 s |
| First cutout | webgpu | Mobile | 8-11 | 2(too few samples) | 12.16 s | 12.30 s | 11.41 s |
| Later cutouts | wasm | Desktop | 8-11 | 1(too few samples) | 3.96 s | 3.96 s | 1.78 s |
| Later cutouts | webgpu | Desktop | 4-7 | 1(too few samples) | 11.58 s | 11.58 s | 9.74 s |
| Later cutouts | webgpu | Desktop | 8-11 | 3(too few samples) | 1.63 s | 2.00 s | 1.29 s |
Baseline (fixed sample set, measured)
Baseline measurement pending: this column has to come from a real run on a named machine, so until that run happens it stays empty rather than holding an estimate.
Sample set
模型固定 768²/512² 输入,耗时随解码与前处理的像素量走、与画面内容无关;合成图把分辨率这一个变量固定住,且任何人都能用仓内脚本生成同样的字节。
自制合成图(CC0)。不含人像,不含任何第三方素材。 · scripts/benchmarks/make-samples.mjs
- s1: 640×480 (0.31 MP)
- s2: 1280×960 (1.23 MP)
- s3: 1920×1440 (2.76 MP)
- s4: 3000×2000 (6 MP)
- s5: 4032×3024 (12.19 MP)
Method and limits
- ·The timers live in src/lib/matting/birefnet-local.js, on the same code path a real cutout takes — there is no separate benchmark mode, so what is measured is what happens after a user presses the button.
- ·Model first download covers the fetch through local gunzip. What crosses the network is 39 MiB of gzip, decompressed locally to 47 MiB, so that row reflects the visitor's network as much as their hardware. Model cache hit is the time to read it back from the Cache API on a later visit.
- ·Runtime load is the ONNX Runtime session creation, including graph optimisation and loading weights into memory. WebGPU is disabled: the WebGPU backend in onnxruntime-web 1.27 produces wrong output on these int8/fp16 weights, and only fp32 is correct but far too large — so only a WASM session is created today, and WebGPU rows in the historical data predate that change.
- ·First and later cutouts are reported separately: the first one also pays for WASM heap growth and the first warm-up of every operator, which is a different thing from the steady state. Collapsing them into one figure misleads both kinds of reader — someone cutting a single image reads it as too fast, someone cutting ten in a row reads it as too slow. "Of which inference" is the session.run segment alone; the remainder is decode, preprocessing and compositing, which scale with image resolution.
- ·p50 and p95 are computed over the raw samples in the window, not by averaging daily percentiles — an average of percentiles carries no statistical meaning.
- ·Samples are self-reported by visitor browsers, with no authentication and no de-duplication: one person cutting ten images contributes ten rows. This page measures the distribution of "how long one cutout takes", not how many people use the tool, and readers should know that limit.
- ·Timing does not depend on image content: the model takes a fixed 1024² input (both the standard BiRefNet_lite fp16 and the “Maximum quality” Swin-Large int8; it falls back to 768 if the 1024 model cannot be fetched, and low-memory devices use 512), and every image is resized to it first. What varies with resolution is decode and preprocessing, not the inference itself.
- ·Device attributes are bucketed in the browser before they are sent (8 cores becomes "8-11"), and the raw values never leave it. So this table can separate orders of magnitude, not specific machine models.
How this page's data is collected
Telemetry sends timing numbers and coarse device buckets only: desktop or mobile, a CPU-core bucket, a memory bucket, an input-resolution bucket, the execution backend, and the model version. It does not send images, any feature derived from an image, filenames, the raw User-Agent, the referrer, or an IP address, and it carries no cookies — there is no field in a sample that points at a person. The privacy policy has the full description.
Privacy policy →Reading telemetry setting…
Download the raw summary
Both formats carry the same content, including the greyed-out rows. Licensed CC BY 4.0; please cite the source and the date you pulled it.