Skip to content

Allow specific splat formats, splat representations and LOD generation methods to be omitted from the WASM blob - #418

Open
mrxz wants to merge 3 commits into
sparkjsdev:mainfrom
mrxz:rust-conditional-compile
Open

Allow specific splat formats, splat representations and LOD generation methods to be omitted from the WASM blob#418
mrxz wants to merge 3 commits into
sparkjsdev:mainfrom
mrxz:rust-conditional-compile

Conversation

@mrxz

@mrxz mrxz commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

Since the format decoding has moved entirely into spark-rs/spark-lib, this also means there is no way for decoders to be tree-shaken or eliminated. As a result the full ~1.5MiB WASM blob is included regardless of which features end up being used. If a user knows ahead of time which splat formats they need, they could theoretically build a WASM blob tailored to their needs. This also extends to whether or not they need online LoD generation or even whether they use ExtSplats/gsplat or PackedSplats/csplat exclusively.

This PR explores using Cargo features to allow specifying which formats, splat representations and lod generation methods to include. The default behaviour remains unchanged (include all features) and on its own this change doesn't enable users to achieve the above mentioned savings yet. Unless you count building a completely custom Spark build. But it's an initial step in this direction and when combined with a way to dynamically load the WASM file instead of embedding it (saving the base64 overhead) this will become usable.

Most features were already nicely abstracted, making selectively excluding them quite trivial. However:

  • Certain configurations result in unused variables, causing the compiler to complain. Probably best to silence them instead of trying to use convoluted #[cfg(....)] predicates, as these will be harder to test/maintain.
  • Since the default wasm-pack behaviour is to also generate the corresponding JS code, naively skipping entire methods results in them missing from the resulting exports as well. In case the .wasm files is dynamically loaded this wouldn't be a big issue, but to enable testing with npm run dev this PR generates stub methods.

@asundqui

asundqui commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

This is a really good idea and a cool solution to making the JS+Rust code all work regardless of settings. I support this. Should we merge @oscarlorentzon @dmarcos ?

@mrxz I'm curious if you did any measurements on WASM blob size reduction in some cases? Like if someone only used csplat+spz, what kind of a % reduction might we expect?

Perhaps you've already examined this but in the past when I optimized Rust-WASM size, I remember one of the big reductions can from eliminating a lot of the exceptional code that is only run on assert/panic failures and similar. With my above question I'm wondering how much is saved from encoding+file type codes, as opposed to all the "support code" that isn't actually in our Rust code but more in the Rust standard library...

@mrxz

mrxz commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator Author

I'm curious if you did any measurements on WASM blob size reduction in some cases? Like if someone only used csplat+spz, what kind of a % reduction might we expect?

Here's a quick comparison between the resulting .wasm file size with the default settings and the combination of just csplat+spz.

Default (everything) csplat+spz Diff
1.486 MiB 0.294 MiB -1.192 MiB (-80.2%)

Perhaps you've already examined this but in the past when I optimized Rust-WASM size, I remember one of the big reductions can from eliminating a lot of the exceptional code that is only run on assert/panic failures and similar. With my above question I'm wondering how much is saved from encoding+file type codes, as opposed to all the "support code" that isn't actually in our Rust code but more in the Rust standard library...

By default wasm-pack already sets the panic strategy to "abort" which improves binary size quite a bit. There's still a lot of Rust "boilerplate/overhead" that gets included, though importantly this doesn't tend to grow beyond a fixed size. For example, having one format string pulls in a lot of string handling code, but from that point onwards it doesn't really matter how many format strings are used. In that sense, I believe even with a minimal configuration as measured above we're already "saturated".

The big savings come in part due to dependencies for certain decoders. For example the SOGS implementation pulls in both zip and image. This is part of the motivation behind #313 as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants