Benchmark: splitting large models in the browser
Quick answer: splicestl v3.3 splits a 200,000-triangle model into 8 pieces with 24 keyed pegs in 5.9 s, and a 1,000,000-triangle model in 34 s, in a browser, on a 2-vCPU container with no GPU. Every output piece is 2-manifold. The same job took 62 s in v3.2; the split now runs in a background worker, so the page stays usable while it works.
- Measured with headless Chromium and the public script
tools/test/bench.js; numbers are wall-clock from clicking Split to the result line. - "Max stall" is the longest the page was unresponsive. With the worker it is the per-cut planning on the main thread, not the geometry.
- Desktop tools are not timed here — the point of this page is a number you can reproduce, not one you have to take on trust.
Results
| Model | Triangles | Split | Connectors | v3.2 split time | v3.3 split time | v3.3 max stall | Pieces manifold |
|---|---|---|---|---|---|---|---|
| UV sphere | 199,080 | 2 × 2 × 2 | 24 pegs, keyed | 62.1 s (31 s stall) | 5.9 s worker · 7.3 s main thread | 1.8 s | 8 / 8 |
| UV sphere | 1,001,112 | 2 × 2 × 2 | 24 pegs, keyed | not run (over 5 min) | 33.8 s worker · 39.8 s main thread | 6.3 s | 8 / 8 |
| UV sphere | 1,001,112 | 2 × 2 × 2 | none | — | 23.5 s worker | 5.7 s | 8 / 8 |
Load time for the 1M-triangle STL (50 MB) was 2.6 s. Peak JavaScript heap was 815 MB with the worker and 1.75 GB on the main thread, which is why the worker path is the default above 40,000 triangles per piece.
Where the time goes (1M triangles, 24 pegs, worker)
Three changes made the difference between v3.2 and v3.3, and none of them is the worker: the connector planner rescanned every triangle on every depth probe (37 s of the old 62 s); each connector cavity was subtracted with its own boolean on the growing piece instead of one compound tool (two booleans per cut instead of fifty); and the post-split weld and fragment passes treated Manifold's exact output like the built-in slicer's, rebuilding it with string-keyed maps. The worker is what keeps the page alive during the 26 s the kernel still needs.
Method
The models are UV spheres of 120 mm diameter generated by tools/test/gen-sphere.py (a sphere is a worst case for connector planning: every cut face is a disc with no flat band). The run is node bench.js sphere1m.stl Pegs 1: load the STL through the file input, "N pieces" 2 × 2 × 2, pegs 5 mm × 8 mm, tolerance 0.2 mm, keyed, flat cuts, engraving off, click Split, wait for the result line. A 50 ms timer measures the longest gap in main-thread responsiveness. Every output piece is checked for boundary edges and edges shared by more than two triangles.
Machine: 2 vCPU, 8 GB, Linux container, Chromium 131 headless (SwiftShader, no GPU) splicestl v3.3 · Manifold 3.3.2 · three.js r128 · three-mesh-bvh 0.7 Repeat: python3 tools/test/gen-sphere.py && node tools/test/bench.js sphere1m.stl Pegs 1
A laptop with a GPU and four or more cores will be faster on every row: the container's two cores are shared between the page, the worker and the browser's own threads.
Against other tools
3D Splitter advertises 2.5 million triangles; LuBan and Split3r run on the desktop CPU with no published figures. None of the three publishes a script, so their numbers cannot be compared to these on equal terms. If you run one of them on the same spheres (the generator is public), send the timing and the machine and it goes in the table with attribution.
What the benchmark does not show
- Shaped cuts (wave, pyramid, jigsaw) cost one extra boolean per cut against a cutter slab; expect 1.5–2× the flat-cut time.
- Dovetail and finger joints run on the main thread and are not yet worker-accelerated.
- Meshes that are not 2-manifold fall back to the built-in slicer, which is slower and produces pieces that need the coarse weld; run Repair first.
What changed — 13 October 2026: first publication, with v3.3.