Loading video...
Video Failed to Load
Ported Google's Draco decoder to pure JavaScript. 4.3× smaller than the WASM build, byte-for-byte identical output, often faster once you factor in load, init and parse.
95,436 views • 3 months ago •via X (Twitter)
49 Comments

This library shines on spotty mobile connections, where transferring 100KB takes much longer than 20KB. Even if JS parsing is slower than WASM, the model displays faster because of the reduction in network overhead.

Managed to reduce the bundle size. It's 5.2× smaller now.

Very cool! A well-optimized JS version of a code like this can match native performance in my experience too. You should try meshopt decoder next! At Mapbox, we have switched from Draco to Meshopt because it's both simpler, faster and generated smaller models for our use case.

Oh! I'll put that on the list 🤓

@mourner Pure JS version is maintained here ;) (it's not particularly optimized, I'm sure it can be faster - getting close to Wasm speed should be impossible however, and the Wasm decoder bundled into JS is pretty tiny, but just in case you need JS-only option)

@mrdoob Happy to see you chime in, amazing project! I guess you mean it’s impossible because of the SIMD build? But for certain cases (e.g a ton of smallish models), JS to WASM comms overhead could be bigger than the SIMD win. Worth an optimization pass attempt at least 😊

I would be quite skeptical; the communication overhead is really just a copy of data in & out of the Wasm heap - it's not free but it's comparatively cheap and it's easy to lose much more on inefficient codegen. It's also not just SIMD; even scalar Wasm often runs faster than optimized JS for these workloads. But of course people should experiment :)

@mrdoob Challenge accepted, I'm really curious! Will do some benchmarking on our typical workloads and report back

@mrdoob You were right! On a typical Mapbox workload (90 buffers, 16.5MB compressed total), baseline JS reference is 14x slower than WASM; after heavy optimization, it's still 3.5x slower. The WASM version is exceptionaly fast and small, and cold start is 4-5ms (negligible)

@fernandojsg Now do KTX2! 😄

@fernandojsg Tempting 😅

you are really ramping up the speed lately

I actually did this back in January with poor Opus 4.5. Decided to do another pass with 4.8 and finish it off today.

This is cool - would be cool to see Cesium's gltf-pipeline for draco for batch compressing built in ( if the scope isnt to have a 1:1 draco port ) :D

Feel free to send a PR or do whatever it's needed 🤗

This feels like a good idea for a lot of cases, make sure to ship a benchmark - cli so agents can do it - so people can use to find the best tool for their job - eg. there's got to be a breaking point where paying the extra is worth it

omg thats big ! 🥳

Thats huge 🤯🤯🤯👏🏻👏🏻👏🏻

Would you recommend to use it already? I use Draco for boats models.

Feel free to give it a go ✌️

@wawasensei Yay! Thx

wasm init was costing me 380ms before a single byte parsed

This further supports my opinion that WASM is just generally not very useful.

@threejs wow

u r awesome

The "once you factor in load and init" line is the unsung headline — for one-shot mesh decodes the WASM startup tax often eats its steady-state win. Bonus is sidestepping the SharedArrayBuffer/COOP header dance the WASM build usually drags into a CDN.

the init time difference is wild. that alone makes it worth it for web use

Some crash on Safari Mobile + littlest Tokyo has no light but overall wonderful project/port

On my Pixel10 at battery saving power mode total improvement is ~1.1x on average. Load+init times are way longer for WASM, up to 400 ms which is user-perceivable. JS parse times are also not that bad. Overall, I agree that JS version is good enough.

JS is fast 💪

Why is the wasm larger?

@threejs Sick!

@threejs 🙌

Oh wow, nice! You know who to ping :)

Haha yes. The man is very busy these days though 😅

@iced_coffee_dev This is pretty cool but it looks like parsing is often slower. This is fine for one off imports but if you are loading a large amount of assets wasm probably wins. I would like to see a benchmark that tests performance at scale.

@iced_coffee_dev Yeah. Do it 👌

That's pretty slick!

Impressive savings and speed boost!

Pure JS port for the real win!

But... in the video WASM rendering shows up before JS - what am I missing?

Thats really nice!

This is awesome, will put it in the 3d model quicklook app

this is a great counterexample to the assumption that wasm is always the right call for web delivery. for long-running compute wasm wins easily. but for draco decoding where each call is short and the init overhead dominates, pure JS can win on total time plus bundle. 4.3x smaller changes the economics for shipping 3d on the web

This is awesome!

used to use Draco, like meshoptimizer better

@iced_coffee_dev Extremely cool!

Parse time is always bigger so for a game with alot of models, .js wont matter as the total parse time would make it par with the .wasm

Yes
