Christopher Hotchkiss

Christopher Hotchkiss

Crafting Solutions, Shaping Products: From Concept to Code

You Just Turn a Knob and it Goes Faster, Right?

July 9, 2026

Adventures in Accelerating OpenSCAD

If it's not obvious, I love solving problems that are useful. They don't always have to be in software and frequently they aren't.

I do a lot of 3d printing and CAD design.

My background is programming so naturally I gravitated to OpenSCAD. It is a wonderful programmatic DSL that produces excellent parametric models.

However OpenSCAD has some issues, it's slow AND it's pretty low level to work with. Fortunately people have built a faster CAD kernel Manifold and higher level building blocks BOSL2.

Together they are great!

But...

They are still too slow for my crazy models AND I was pretty convinced that it wasn't because of the CAD kernel but rather the interpreted DSL that then calls Manifold. Also when using the WASM compiled version of OpenSCAD+Manifold, the stack overflows on even my most basic models.

So me being me, I decided it's been years since I've done a parser/lexer so let's just rewrite it, surely I could inline some of the functions and it'll be easy to get a nice big speed up. Right?

This conviction stemmed from the fact that BOSL2 does a ton of math / list operations inside the SCAD language so if I could lift the worst functions into native code it would cut the overhead a lot.

Note: This is the part of the show where Chris realizes he bit off more than maybe he bargained for.

So the code base is here: chotchki/fab-scad and there are some cool things in it:

  • lang/ - has a pure parser+interpreter of the OpenSCAD language
  • tests/ - has all the comparative test harnesses to ensure we match openscad

I've held to 100% test coverage of this part of the project because if nothing else comes of this, it would be great for regression tests!

Current State

So currently there are three different levels of the rewrite functioning: a fully interpreted, interpreted with selected functions hand rewritten to native code and finally the start of using Cranelift to JIT compile the code.

Shockingly when I finished the interpreter and tested it against one of my models, it was about on par with OpenSCAD, however when profiled my version was super fast calling Manifold while OpenSCAD's interpreter beat the pants off me. It all balanced out in the end.

Where the data is currently pointing me is that to get REAL performance improvements on complicated BOSL2 based models, I'm going to have to JIT compile the DSL and inline as many function calls as I can. That'll require the slow invention of a JIT calling convention since with Cranelift you don't get to pretend all the nasty low level stuff doesn't exist.

Microbenchmarks

Just to give a grossly unfair example of one function of what may be possible. This is just on language evaluation the actual CAD kernel is the same under the hood (Manifold).

is_nan(x) = (x != x) ns/call vs OpenSCAD what changed
OpenSCAD (C++) 497.5 1.0× baseline (C++ tree-walker)
fab-scad interpreter 294.2 1.7× our Rust tree-walker, still boxing Values
fab-scad intrinsic 4.1 122× native Rust body replacing the interpreted one
fab-scad JIT 1.8 282× Cranelift native code, no boxing

Either way I'm having fun working on it and have rightly been accused of yak shaving the yak twice over by Claude but it's been a great learning experience.

Cover Image from Luzhou Ye, CC BY-SA 3.0, via Wikimedia Commons