Binary size and features
Pay only for what you use. One feature table turns BUI's optional parts (image formats, video, the GPU renderers, the file browser, Dear ImGui) on or off in CMake, cargo and bui build, and bui build links the smallest runtime an app needs. Measured sizes.
- C
- Rust
- JavaScript
- Python
A feature should cost binary size only if you use it. BUI’s optional parts are one table, features.json, and three tools read it:
- CMake (
features.cmake): one option each,ONby default (-DBUI_VIDEO=OFF). See CMake options. - cargo: the same names are features of
blenderui-sysandblenderui, all on by default.blenderui-sys/build.rsmaps each to its CMake option and stops the build ifCargo.tomlmisses one; a test checksblenderuiforwards them all. bui build: links the smallest prebuilt runtime that has what the app uses.
Off, a part’s sources aren’t compiled at all. Its API stays, so code compiles either way: a missing format doesn’t decode, a video reports an error state, BK_file_dialog returns -1, and windows draw with the software raster.
| Feature | What it is |
|---|---|
png, gif, bmp, tga, qoi |
Those formats (Wuffs, only the modules on) |
jpeg |
libjpeg-turbo |
webp |
libwebp (with animations) |
hdr, pnm |
BUI’s readers |
svg |
SVG images (nanosvg, which the icons need anyway) |
video |
Video through the OS, loaded at run time |
gpu |
Direct3D 11 / OpenGL renderers |
freetype |
FreeType text (else stb_truetype) |
filebrowser |
Blender’s File Browser and BK_file_dialog |
imgui |
Dear ImGui on BUI (cargo: off unless blenderui-imgui asks) |
Rust
[dependencies]# only what this app shows: no JPEG, WebP, video, GPU or file browser codeblenderui = { version = "0.3", default-features = false, features = ["slug", "png", "svg", "freetype"] }bui build
Rebuilding the runtime per app would need a Rust and C toolchain on every machine that runs bui build. Splitting it into a core and loadable modules would cost a dynamic-library boundary (no whole-program LTO across it) and more files to ship. So the package ships a few prebuilt runtimes, listed in features.json, and bui build appends the app to the smallest one that has every feature the app needs: no compiler, and the same one-file executable.
| Runtime | Has |
|---|---|
base |
UI, text, SVG images |
media |
base + every image format + video |
full |
media + the GPU renderer + the file browser |
How bui build decides, explicit first:
--features png,videoon the command line;"bui": { "features": ["png", "video"] }in the app’spackage.json;- otherwise, it looks in the bundle:
<video>elements, media file names in string literals ("logo.webp","intro.mp4") and file dialogs.
It prints its choice (bui: runtime "media" for png, video). A path built at run time ("photo." + ext, a file the user picks) can’t be seen in the bundle, and the GPU renderer is never detected (the library’s own code mentions its option): list those features explicitly. A feature no prebuilt runtime has is an error that says so.
Measured
bui build: what an app pays for
bui-runtime by the features it has (Windows x64, fat LTO)
Lower is better
0.6 MBsmaller for an app without images or video
- baseUI, text, SVG6.15 MB
- media+ images, video6.72 MB
- full+ GPU, file browser6.81 MB
Open benchClose bench
| Runtime / app | Kit features | Bytes | MB |
|---|---|---|---|
| base runtime | UI, text (FreeType), SVG | 6,444,544 | 6.15 |
| base + video | + video (Media Foundation) | 6,447,616 (+3,072) | 6.15 |
| base + GPU | + Direct3D 11 renderer | 6,486,528 (+41,984) | 6.19 |
| images runtime | + PNG, GIF, BMP, TGA, QOI, JPEG, WebP, HDR, PNM | 7,040,512 (+595,968) | 6.71 |
| media runtime | + every image format + video | 7,047,680 | 6.72 |
| full runtime | + GPU renderer + file browser | 7,139,328 | 6.81 |
| full, before video (v0.3.0 tree + images) | everything then | 7,097,856 | 6.77 |
| hello-world app (bui build) | base + 175 KB bundle | 6,619,464 | 6.31 |
| images app (bui build) | media + bundle | 7,222,630 | 6.89 |
| video app (bui build) | media + bundle | 7,222,603 | 6.89 |
Measured with bindings/node/scripts/build.js (cargo build -p blenderui-qjs --profile dist --no-default-features --features blenderui/...): the runtimes features.json lists, and single-feature variants for the deltas. The apps are bindings/node/bench/size/*.jsx built with `bui build`, which picked the runtime from the bundle (hello: base; images and video: media). What every runtime keeps: QuickJS, Rust's std, the CSS/Tailwind engine and layout, Blender's icons (about 0.8 MB of SVG data) and the embedded Inter font.
Source: features.json · Ryzen 7 5800U laptop, Windows 11, on AC power
By feature, on Windows x64 with fat LTO: every image format together is about 596 KB (most of it libwebp and libjpeg-turbo), video 3 KB (the OS decodes; Media Foundation is loaded at run time), the Direct3D 11 renderer 42 KB and the file browser about 50 KB. The base runtime is about a tenth smaller than the full one; most of what remains is the same for every app: QuickJS, Rust’s standard library, the CSS and layout engine, Blender’s icons and the embedded Inter font. The Python wheel, the Node addon and cargo builds with default features have everything.
Last updated