Skip to content

ESP32 size: −34.7 KB, below the last release again - #567

Merged
mariusandra merged 2 commits into
mainfrom
esp32-size-trim
Oct 18, 2026
Merged

mariusandra merged 2 commits into
mainfrom
esp32-size-trim

Conversation

@mariusandra

Copy link
Copy Markdown
Collaborator

Main had grown +15,952 B of ESP32 firmware since v2026.10.15 (3,138,272 → 3,154,224; the release tree rebuilt locally matches the published image byte for byte). This PR takes it to 3,119,504 B: −34,720 against main, 18,768 B under the release, OTA slot 87.5% → 86.5%. The audit of what went in and both passes are written up in docs/esp32-image-size.md.

What went in since 2026.10.15

object Δ PRs
redacted_url.nim (new) +3,154 #564
fos_panel_draw.c / fos_status_screen.c +2,229 / −1,156 #560
app_runtime.nim (prelude literal +1,274) +2,216 #553 #556 #563 #564
http_client.nim +1,815 #564 #565
fos_netguard.c +1,353 #560 #564 #566
input_state.nim +1,313 #554 #557 #562
LAN code, Nim glue, fos_client.c, deadline message, buttons/buzzer ~+3,900

The C side is feature code. The Nim side carried duplicates.

Commit 1: what was there twice (−4,960, no behaviour change)

  • On ESP32 redactedUrl calls the C fos_netguard_url_origin instead of keeping a Nim twin (the Nim test cases pass against it).
  • No generic string slices in redactedUrlsIn / httpHostOf (each module that slices gets its own ~350 B copy). httpHostOf is now redactedUrl minus the scheme, so an unparseable URL no longer falls back to the whole URL in the deadline message.
  • compactJs: the JS preludes lose indentation, blank and // lines at compile time (guarded against template literals and trailing backslashes); the frameos asset/stream calls share helpers; console points at frameos.log / frameos.error, with a new test.
  • The status SVG's comment and duplicate JSON lookups in button input.

Commit 2: one copy of each Nim inline helper (−29,760)

Nim writes every inline helper into each C file that calls it (70 appendStrings, 44 nimDecRefIsLastCyclicDyns, …). embedded/esp32/tools/fold_nim_inlines.py, run by build_nim.sh, rewrites helpers whose definition is identical in every file as C99 inline, with extern inline in one owner file. GCC still inlines where it wants; every other call goes to one copy. 199 fold, 23 that read module data stay. (weak was tried and made it 1.4 KB bigger: GCC never inlines weak functions.)

Testing

  • Host Nim tests for every touched module, plus seven heavy suites (interpreter, event fixtures, single-scene host, JS app runtime, all 19 repo app suites) built through the fold at -O0, so every call hits the single copy: all pass.
  • test_esp32_fold_nim_inlines.py: the rewrite, the cases that must not fold, and a folded sample linked and run at -O0 and -O2.
  • test_fos_netguard.c (222 checks), generate_scene_guide.py --check.
  • ci_build_image.sh in the esp32-ci image: 3,119,504 B; QEMU smoke boots as far as main does (both stop before app_main).

Not done: a hardware run. The fold rewrites generated C, so this wants a bench pass on the E1002 (a render, a JS app scene, a button press) before merging.

🤖 Generated with Claude Code

mariusandra and others added 2 commits October 18, 2026 13:16
Main had grown +15,952 B of firmware since v2026.10.15. The C side of that
is feature code; five things on the Nim side were redundant, and none of
the changes alters behaviour:

- redactedUrl existed in Nim (1,570 B) and in C (fos_netguard_url_origin),
  which the firmware links anyway. On frameosEmbedded the Nim proc calls
  the C one; the Nim test cases pass against it (built on the host with
  -d:frameosEmbedded and fos_netguard.c).
- A string slice `s[a .. b]` is a generic instantiated anew, ~350 B, in
  every module that uses one. redactedUrlsIn and httpHostOf use substr.
  httpHostOf is now redactedUrl without the scheme, so a URL it cannot
  parse reads "(invalid URL)" instead of the whole URL.
- The JS preludes shipped their indentation and comments. compactJs
  (burrito.nim, compile time) trims each line and drops blank and `//`
  lines, and refuses a template literal or a trailing backslash, the two
  ways a string could run across lines. The asset and stream calls of
  `frameos` share three helpers; console points at frameos.log and
  frameos.error (with a test of its own, outside the test harness).
- The status screen's SVG opened with a 330-byte comment, cut at compile
  time.
- input_state.button looked up atMs, durationMs and level twice each.

esp32-s3: 3,154,224 → 3,149,264 B.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…29,760 B)

Nim emits every {.inline.} proc a module needs as `static N_INLINE` into
that module's C file, and wherever GCC does not inline a call the file
keeps a private copy: 70 appendStrings, 44 nimDecRefIsLastCyclicDyns, 31
eqStrings, a dozen of each string slice's `[]`, about 21.6 KB of identical
code.

embedded/esp32/tools/fold_nim_inlines.py, run by build_nim.sh, uses C99
inline semantics: a helper defined identically in every file becomes a
plain `inline` definition (still inlinable, no private copy) everywhere
but one file, whose `extern inline` is the single external definition.
Bodies are compared after renaming the temporaries each declares (Nim
names them after the module); one that reads module data, or has a static
local, stays as it was. 199 helpers fold, 23 stay.

`weak` folds the copies too, but GCC never inlines a weak function and
that cost more than it saved (+1,392 B net, measured).

Checked: seven host suites (interpreter, dispatcher fixtures, single-scene
host, JS app runtime, all 19 repo app suites) built through the same fold
at -O0, where every call goes to the one copy, pass;
test_esp32_fold_nim_inlines.py pins the rewrite and links and runs a
folded sample at -O0 and -O2; the QEMU smoke boots it as far as it boots
main. Not yet run on hardware.

esp32-s3: 3,149,264 → 3,119,504 B, 18,768 B under v2026.10.15. The audit
of what went in since that release and both passes are in
docs/esp32-image-size.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

ESP32 firmware size

Built from 36ca24f by this run; compared with the latest release v2026.10.15.

Image This PR v2026.10.15 Δ
esp32-s3 app (OTA image) 3,119,504
86.5% of 3520K slot, 474 KB free
3,138,272 -18,768 (-0.6%)
esp32-s3 merged flash image 3,185,040 3,203,808 -18,768 (-0.6%)
esp32-s3-32mb app (OTA image) 3,119,488
75.6% of 4032K slot, 986 KB free
3,138,272 -18,784 (-0.6%)
esp32-s3-32mb merged flash image 3,250,560 3,269,344 -18,784 (-0.6%)

Breakdown by subsystem — esp32-s3

Subsystem This PR v2026.10.15 Δ
FrameOS core (Nim) 475,930 477,042 -1,112 (-0.2%)
QuickJS 360,285 360,373 -88 (-0.0%)
pixie 296,959 304,354 -7,395 (-2.4%)
Wi-Fi stack 295,296 295,304 -8 (-0.0%)
Nim stdlib 247,612 251,436 -3,824 (-1.5%)
FrameOS apps (Nim) 181,348 190,356 -9,008 (-4.7%)
ESP-IDF misc 181,343 181,564 -221 (-0.1%)
Embedded font 146,358 146,362 -4 (-0.0%)
String pool (attributed to efuse) 136,729 136,134 +595 (+0.4%)
fos_* firmware shell (C) 136,501 132,233 +4,268 (+3.2%)
mbedTLS + certificates 132,427 132,439 -12 (-0.0%)
lwIP / HTTP / WebSocket 126,939 126,800 +139 (+0.1%)
libc / libm / newlib 116,263 116,263 ±0
Storage (SPIFFS / FatFS / SD / NVS) 94,068 94,080 -12 (-0.0%)
Nim packages (chrono, zippy, chroma, qrgen, ...) 70,320 71,849 -1,529 (-2.1%)
Display drivers (C) 64,962 64,946 +16 (+0.0%)
Crypto (monocypher) 35,141 35,141 ±0
Total mapped flash 3,098,481 3,116,676 -18,195 (-0.6%)
Inside each subsystem

FrameOS core (Nim) — 475,930

Part This PR v2026.10.15 Δ
frameos/js_runtime 115,612 115,444 +168 (+0.1%)
frameos/utils 110,853 112,401 -1,548 (-1.4%)
frameos/interpreter.nim 100,659 100,264 +395 (+0.4%)
embedded_main.nim 19,120 19,252 -132 (-0.7%)
embedded_runtime.nim 17,593 17,834 -241 (-1.4%)
lib/tz.nim 16,589 16,722 -133 (-0.8%)
frameos_nim_glue.c.obj 11,455 10,635 +820 (+7.7%)
frameos/planner.nim 9,574 9,681 -107 (-1.1%)
frameos/event_loop.nim 8,143 8,412 -269 (-3.2%)
frameos/types.nim 7,715 7,909 -194 (-2.5%)
frameos/values.nim 7,528 7,699 -171 (-2.2%)
frameos/single_scene_host.nim 6,379 6,712 -333 (-5.0%)
frameos/apps.nim 6,431 6,585 -154 (-2.3%)
frameos/spool.nim 5,560 5,787 -227 (-3.9%)
embedded_scene.nim 4,654 4,945 -291 (-5.9%)
frameos/input_state.nim 4,676 3,766 +910 (+24.2%)
frameos/events_gen.nim 3,967 3,948 +19 (+0.5%)
fos_netguard.c.obj 3,532 2,179 +1,353 (+62.1%)
frameos/app_config.nim 2,734 2,935 -201 (-6.8%)
frameos/reboot_reason.nim 2,332 2,648 -316 (-11.9%)
frameos/node_config.nim 2,582 2,618 -36 (-1.4%)
frameos/app_capabilities.nim 2,473 2,489 -16 (-0.6%)
frameos/events.nim 2,335 2,410 -75 (-3.1%)
frameos/refresh_interval.nim 1,593 1,639 -46 (-2.8%)
frameos/runtime_diagnostics.nim 775 767 +8 (+1.0%)
frameos/event_log.nim 407 431 -24 (-5.6%)
fos_version.c.obj 328 328 ±0
frameos/cloud — 255 -255 (-100.0%)
frameos/channels.nim 153 152 +1 (+0.7%)
frameos/ids.nim 120 137 -17 (-12.4%)
frameos/hal 44 44 ±0
frameos/retired_apps.nim 14 14 ±0

QuickJS — 360,285

Part This PR v2026.10.15 Δ
quickjs.c.obj 287,746 287,846 -100 (-0.0%)
libunicode.c.obj 50,178 50,178 ±0
libregexp.c.obj 14,007 13,999 +8 (+0.1%)
dtoa.c.obj 5,689 5,685 +4 (+0.1%)
cutils.c.obj 2,141 2,141 ±0
fos_qjs_glue.c.obj 449 449 ±0
fos_quickjs_tz.c.obj 75 75 ±0

pixie — 296,959

Part This PR v2026.10.15 Δ
pixie/fontformats/opentype.nim 56,066 55,460 +606 (+1.1%)
pixie/fileformats/webp.nim 36,937 37,493 -556 (-1.5%)
pixie/fileformats/svg.nim 35,546 36,983 -1,437 (-3.9%)
pixie/paths.nim 31,616 32,875 -1,259 (-3.8%)
pixie/fileformats/jpeg.nim 29,164 29,436 -272 (-0.9%)
pixie/fileformats/png.nim 21,475 22,101 -626 (-2.8%)
pixie/images.nim 15,445 15,779 -334 (-2.1%)
pixie/fonts.nim 10,301 10,995 -694 (-6.3%)
pixie/paints.nim 9,023 9,869 -846 (-8.6%)
pixie/fileformats/bmp.nim 7,612 8,258 -646 (-7.8%)
pixie/common.nim 7,158 7,413 -255 (-3.4%)
pixie/blends.nim 6,622 6,516 +106 (+1.6%)
pixie/fileformats/gif.nim 5,737 5,965 -228 (-3.8%)
pixie.nim 5,243 5,224 +19 (+0.4%)
pixie/inflatestream.nim 5,156 5,233 -77 (-1.5%)
pixie/fileformats/webp_vp8_tables.nim 3,881 3,881 ±0
pixie/fileformats/ppm.nim 3,520 3,713 -193 (-5.2%)
pixie/contexts.nim 2,951 3,054 -103 (-3.4%)
pixie/fileformats/qoi.nim 2,437 2,702 -265 (-9.8%)
pixie/internal.nim 502 754 -252 (-33.4%)
pixie/rgb565.nim 327 385 -58 (-15.1%)
pixie/fontformats/svgfont.nim 190 215 -25 (-11.6%)
pixie/decodebudget.nim 50 50 ±0

Wi-Fi stack — 295,296

Part This PR v2026.10.15 Δ
libnet80211.a 136,148 136,168 -20 (-0.0%)
libpp.a 62,158 62,154 +4 (+0.0%)
libwpa_supplicant.a 54,904 54,904 ±0
libphy.a 34,176 34,176 ±0
libesp_wifi.a 4,788 4,780 +8 (+0.2%)
libesp_phy.a 2,541 2,541 ±0
libesp_coex.a 291 291 ±0
libcore.a 287 287 ±0
libespnow.a 3 3 ±0

Nim stdlib — 247,612

Part This PR v2026.10.15 Δ
pure/collections/tables.nim 72,114 72,312 -198 (-0.3%)
system.nim 48,163 48,457 -294 (-0.6%)
pure/unicode.nim 17,324 17,405 -81 (-0.5%)
pure/times.nim 16,493 16,888 -395 (-2.3%)
pure/json.nim 13,478 13,722 -244 (-1.8%)
std/private/dragonbox.nim 10,348 10,351 -3 (-0.0%)
pure/strutils.nim 7,847 8,047 -200 (-2.5%)
pure/parsexml.nim 5,802 6,011 -209 (-3.5%)
pure/algorithm.nim 5,324 5,372 -48 (-0.9%)
pure/base64.nim 5,107 5,290 -183 (-3.5%)
pure/hashes.nim 4,003 4,181 -178 (-4.3%)
pure/xmlparser.nim 3,407 3,555 -148 (-4.2%)
pure/parsejson.nim 3,392 3,553 -161 (-4.5%)
std/formatfloat.nim 3,476 3,504 -28 (-0.8%)
pure/uri.nim 2,988 3,225 -237 (-7.3%)
pure/streams.nim 2,749 2,820 -71 (-2.5%)
pure/strformat.nim 2,380 2,546 -166 (-6.5%)
std/syncio.nim 2,282 2,355 -73 (-3.1%)
pure/collections/sets.nim 2,089 2,075 +14 (+0.7%)
pure/xmltree.nim 1,862 2,047 -185 (-9.0%)
pure/lexbase.nim 1,775 1,801 -26 (-1.4%)
pure/parseutils.nim 1,741 1,750 -9 (-0.5%)
system/exceptions.nim 1,530 1,598 -68 (-4.3%)
pure/strtabs.nim 1,507 1,572 -65 (-4.1%)
pure/pathnorm.nim 1,212 1,336 -124 (-9.3%)
pure/options.nim 815 1,016 -201 (-19.8%)
std/private/ospaths2.nim 966 994 -28 (-2.8%)
pure/collections/lists.nim 990 979 +11 (+1.1%)
pure/collections/deques.nim 844 822 +22 (+2.7%)
pure/math.nim 839 841 -2 (-0.2%)
pure/random.nim 688 696 -8 (-1.1%)
std/private/digitsutils.nim 617 651 -34 (-5.2%)
std/oserrors.nim 489 633 -144 (-22.7%)
std/private/osdirs.nim 510 572 -62 (-10.8%)
system/dollars.nim 431 529 -98 (-18.5%)
std/monotimes.nim 485 406 +79 (+19.5%)
std/private/oscommon.nim 325 329 -4 (-1.2%)
std/envvars.nim 310 250 +60 (+24.0%)
std/private/decode_helpers.nim 181 240 -59 (-24.6%)
std/private/ossymlinks.nim 187 187 ±0
pure/bitops.nim 162 162 ±0
pure/os.nim 99 99 ±0
std/private/osfiles.nim 96 96 ±0
core/macros.nim 89 65 +24 (+36.9%)
std/assertions.nim 87 87 ±0
system/ctypes.nim 9 9 ±0

FrameOS apps (Nim) — 181,348

Part This PR v2026.10.15 Δ
apps/data/icalJson 50,262 50,733 -471 (-0.9%)
apps/render/calendar 29,944 30,874 -930 (-3.0%)
apps/data/localImage 10,340 10,432 -92 (-0.9%)
apps/render/split 9,389 9,772 -383 (-3.9%)
apps/data/eventsToAgenda 8,568 9,068 -500 (-5.5%)
apps/render/zoomPan 8,360 8,648 -288 (-3.3%)
apps/apps.nim 7,208 7,247 -39 (-0.5%)
apps/render/text 5,234 5,455 -221 (-4.1%)
apps/data/xmlToJson 5,190 5,428 -238 (-4.4%)
apps/render/svg 4,583 5,192 -609 (-11.7%)
apps/render/image 4,423 4,708 -285 (-6.1%)
apps/data/rotateImage 2,939 3,465 -526 (-15.2%)
apps/logic/setAsState 3,181 3,453 -272 (-7.9%)
apps/data/downloadImage 3,128 3,325 -197 (-5.9%)
apps/render/gradient 2,983 3,229 -246 (-7.6%)
apps/data/qr 3,017 3,122 -105 (-3.4%)
apps/data/downloadUrl 2,774 3,053 -279 (-9.1%)
apps/render/color 2,059 2,824 -765 (-27.1%)
apps/data/newImage 2,175 2,668 -493 (-18.5%)
apps/data/resizeImage 2,312 2,558 -246 (-9.6%)
apps/data/log 2,053 2,299 -246 (-10.7%)
apps/render/opacity 2,055 2,296 -241 (-10.5%)
apps/data/prettyJson 1,947 2,225 -278 (-12.5%)
apps/data/clock 1,718 1,875 -157 (-8.4%)
apps/data/parseJson 1,585 1,856 -271 (-14.6%)
apps/logic/nextSleepDuration 1,394 1,663 -269 (-16.2%)
apps/logic/ifElse 1,311 1,494 -183 (-12.2%)
apps/logic/breakIfRendering 1,216 1,394 -178 (-12.8%)

ESP-IDF misc — 181,343

Part This PR v2026.10.15 Δ
libesp_hw_support.a 37,620 37,632 -12 (-0.0%)
libhal.a 21,865 21,865 ±0
libfreertos.a 17,240 17,240 ±0
libesp_system.a 13,736 13,780 -44 (-0.3%)
libesp_driver_uart.a 11,627 11,627 ±0
libheap.a 8,660 8,660 ±0
libesp_driver_i2c.a 8,062 8,062 ±0
libesp_driver_spi.a 7,760 7,756 +4 (+0.1%)
libconsole.a 5,733 5,733 ±0
libjson.a 4,940 4,940 ±0
libesp_driver_gpio.a 3,878 3,878 ±0
libbootloader_support.a 3,813 3,813 ±0
libxtensa.a 3,691 3,691 ±0
libesp_driver_usb_serial_jtag.a 3,408 3,408 ±0
libesp_ringbuf.a 3,322 3,322 ±0
libesp_event.a 3,241 3,253 -12 (-0.4%)
libesp_driver_ledc.a 3,054 3,054 ±0
libesp_mm.a 2,451 2,451 ±0
libapp_update.a 2,414 2,414 ±0
libesp_timer.a 2,337 2,337 ±0
libesp_psram.a 2,172 2,329 -157 (-6.7%)
libsoc.a 2,316 2,316 ±0
libesp_adc.a 2,285 2,285 ±0
libpthread.a 1,397 1,397 ±0
liblog.a 1,375 1,375 ±0
libesp_security.a 1,050 1,050 ±0
libesp_rom.a 902 902 ±0
libesp_app_format.a 507 507 ±0
libxt_hal.a 437 437 ±0
libesp_common.a 26 26 ±0
libesp_pm.a 24 24 ±0

Embedded font — 146,358

Part This PR v2026.10.15 Δ
assets/fonts.nim 146,358 146,362 -4 (-0.0%)

String pool (attributed to efuse) — 136,729

Part This PR v2026.10.15 Δ
esp_efuse_utility.c.obj 135,683 135,088 +595 (+0.4%)
esp_efuse_rtc_calib.c.obj 566 566 ±0
esp_efuse_table.c.obj 268 268 ±0
esp_efuse_api.c.obj 151 151 ±0
esp_efuse_startup.c.obj 61 61 ±0

fos_ firmware shell (C)* — 136,501

Part This PR v2026.10.15 Δ
fos_http.c.obj 22,185 22,185 ±0
fos_cloud.c.obj 19,651 19,258 +393 (+2.0%)
fos_console.c.obj 14,001 13,950 +51 (+0.4%)
fos_client.c.obj 12,957 12,266 +691 (+5.6%)
fos_settings.c.obj 7,722 7,618 +104 (+1.4%)
fos_scenes.c.obj 7,515 7,578 -63 (-0.8%)
fos_ota.c.obj 5,639 5,467 +172 (+3.1%)
fos_cloud_contract.c.obj 4,768 4,744 +24 (+0.5%)
fos_config.c.obj 4,619 4,619 ±0
fos_wifi.c.obj 3,189 3,189 ±0
fos_assets.c.obj 3,124 3,124 ±0
fos_sd_probe.c.obj 2,753 2,753 ±0
fos_buttons.c.obj 2,737 2,493 +244 (+9.8%)
fos_schedule.c.obj 2,614 2,602 +12 (+0.5%)
fos_assets_sd.c.obj 2,484 2,484 ±0
fos_events.c.obj 2,332 2,320 +12 (+0.5%)
fos_panel_draw.c.obj 2,229 — +2,229
fos_status_screen.c.obj 893 2,049 -1,156 (-56.4%)
main.c.obj 1,703 1,699 +4 (+0.2%)
fos_config_parse.c.obj 1,467 1,467 ±0
fos_url_guard.c.obj 1,397 1,397 ±0
fos_tz.c.obj 1,294 1,294 ±0
fos_buzzer.c.obj 1,162 901 +261 (+29.0%)
fos_battery.c.obj 1,140 1,140 ±0
fos_minisig.c.obj 1,140 1,140 ±0
fos_backend_http.c.obj 1,072 1,072 ±0
fos_commands.c.obj 940 940 ±0
fos_lan_access.c.obj 841 — +841
fos_scene_state.c.obj 650 650 ±0
fos_framebuffer.c.obj 483 483 ±0
fos_button_timing.c.obj 434 — +434
fos_board.c.obj 334 334 ±0
fos_assets_path.c.obj 259 259 ±0
fos_power.c.obj 241 241 ±0
fos_battery_filter.c.obj 214 214 ±0
fos_wake.c.obj 199 184 +15 (+8.2%)
fos_json_guard.c.obj 119 119 ±0

mbedTLS + certificates — 132,427

Part This PR v2026.10.15 Δ
libmbedcrypto.a 71,291 71,291 ±0
libmbedtls.a 45,799 45,799 ±0
libmbedx509.a 7,080 7,092 -12 (-0.2%)
libesp-tls.a 6,705 6,705 ±0
libesp_https_server.a 1,552 1,552 ±0

lwIP / HTTP / WebSocket — 126,939

Part This PR v2026.10.15 Δ
liblwip.a 78,529 78,445 +84 (+0.1%)
libhttp_parser.a 10,350 10,350 ±0
libesp_http_server.a 10,020 10,020 ±0
libtcp_transport.a 8,245 8,245 ±0
libespressif__esp_websocket_client.a 6,822 6,822 ±0
libesp_http_client.a 6,666 6,666 ±0
libesp_netif.a 6,307 6,252 +55 (+0.9%)

libc / libm / newlib — 116,263

Part This PR v2026.10.15 Δ
libc.a 76,471 76,471 ±0
libm.a 31,563 31,563 ±0
libnewlib.a 6,609 6,609 ±0
libstdc++.a 1,476 1,476 ±0
libgcc.a 98 98 ±0
libcxx.a 46 46 ±0

Storage (SPIFFS / FatFS / SD / NVS) — 94,068

Part This PR v2026.10.15 Δ
libspiffs.a 20,380 20,380 ±0
libfatfs.a 20,141 20,133 +8 (+0.0%)
libspi_flash.a 14,168 14,168 ±0
libnvs_flash.a 13,665 13,685 -20 (-0.1%)
libsdmmc.a 13,013 13,013 ±0
libvfs.a 6,196 6,196 ±0
libesp_driver_sdspi.a 3,866 3,866 ±0
libesp_partition.a 1,956 1,956 ±0
libesp_vfs_console.a 678 678 ±0
libnvs_sec_provider.a 5 5 ±0

Nim packages (chrono, zippy, chroma, qrgen, ...) — 70,320

Part This PR v2026.10.15 Δ
QRgen 3.1.0 21,886 22,060 -174 (-0.8%)
chrono 0.3.1 15,049 15,586 -537 (-3.4%)
zippy 0.10.19 14,936 15,200 -264 (-1.7%)
chroma 1.0.0 14,368 14,714 -346 (-2.4%)
checksums 0.2.1 3,290 3,371 -81 (-2.4%)
flatty 0.3.4 530 533 -3 (-0.6%)
jsony 1.1.5 148 272 -124 (-45.6%)
bumpy 1.1.3 113 113 ±0

Display drivers (C) — 64,962

Part This PR v2026.10.15 Δ
(everything else) 21,278 21,282 -4 (-0.0%)
frameos_panel_table.c.obj 6,685 6,685 ±0
EPD_13in3e.c.obj 1,796 1,796 ±0
EPD_3in7.c.obj 1,564 1,564 ±0
EPD_5in79.c.obj 1,481 1,481 ±0
DEV_Debug.c.obj 1,313 1,317 -4 (-0.3%)
EPD_2in7.c.obj 1,292 1,292 ±0
EPD_4in2.c.obj 1,262 1,262 ±0
EPD_7in3e.c.obj 1,208 1,208 ±0
EPD_4in2_V2.c.obj 1,184 1,184 ±0
DEV_Config_esp.c.obj 1,180 1,180 ±0
EPD_4in26.c.obj 1,123 1,123 ±0
29 smaller rows 23,596 23,572 +24 (+0.1%)

Crypto (monocypher) — 35,141

Part This PR v2026.10.15 Δ
monocypher.c.obj 31,916 31,916 ±0
monocypher-ed25519.c.obj 3,225 3,225 ±0
Biggest movers (per object)
Object Δ This PR Baseline
frameos/input_state.nim +4,676 4,676 —
pkgs/QRgen-3.1.0/QRgen/renderer.nim -3,780 — 3,780
pkgs/pixie-6.1.0/pixie/fileformats/svg.nim -1,437 35,546 36,983
frameos/utils/status_screen.nim -1,392 16,551 17,943
pkgs/pixie-6.1.0/pixie/paths.nim -1,259 31,616 32,875
apps/render/calendar/app.nim -976 22,841 23,817
pkgs/pixie-6.1.0/pixie/paints.nim -846 9,023 9,869
frameos/utils/http_client.nim +821 10,811 9,990
frameos_nim_glue.c.obj +820 11,455 10,635
pkgs/pixie-6.1.0/pixie/fonts.nim -694 10,301 10,995
fos_client.c.obj +691 12,957 12,266
frameos/utils/image.nim -683 35,259 35,942
pkgs/pixie-6.1.0/pixie/fileformats/bmp.nim -646 7,612 8,258
pkgs/pixie-6.1.0/pixie/fileformats/png.nim -626 21,475 22,101
pkgs/pixie-6.1.0/pixie/fontformats/opentype.nim +606 56,066 55,460
Largest 30 objects
Object Subsystem This PR v2026.10.15 Δ
quickjs.c.obj QuickJS 287,746 287,846 -100 (-0.0%)
assets/fonts.nim Embedded font 146,358 146,362 -4 (-0.0%)
esp_efuse_utility.c.obj String pool (attributed to efuse) 135,683 135,088 +595 (+0.4%)
frameos/interpreter.nim FrameOS core (Nim) 100,659 100,264 +395 (+0.4%)
frameos/js_runtime/app_runtime.nim FrameOS core (Nim) 72,782 72,635 +147 (+0.2%)
nim/lib/pure/collections/tables.nim Nim stdlib 72,114 72,312 -198 (-0.3%)
pkgs/pixie-6.1.0/pixie/fontformats/opentype.nim pixie 56,066 55,460 +606 (+1.1%)
libunicode.c.obj QuickJS 50,178 50,178 ±0
nim/lib/system.nim Nim stdlib 48,163 48,457 -294 (-0.6%)
apps/data/icalJson/ical.nim FrameOS apps (Nim) 44,746 45,016 -270 (-0.6%)
pkgs/pixie-6.1.0/pixie/fileformats/webp.nim pixie 36,937 37,493 -556 (-1.5%)
pkgs/pixie-6.1.0/pixie/fileformats/svg.nim pixie 35,546 36,983 -1,437 (-3.9%)
frameos/utils/image.nim FrameOS core (Nim) 35,259 35,942 -683 (-1.9%)
monocypher.c.obj Crypto (monocypher) 31,916 31,916 ±0
pkgs/pixie-6.1.0/pixie/paths.nim pixie 31,616 32,875 -1,259 (-3.8%)
frameos/js_runtime/runtime.nim FrameOS core (Nim) 31,330 31,686 -356 (-1.1%)
pkgs/pixie-6.1.0/pixie/fileformats/jpeg.nim pixie 29,164 29,436 -272 (-0.9%)
apps/render/calendar/app.nim FrameOS apps (Nim) 22,841 23,817 -976 (-4.1%)
fos_http.c.obj fos_* firmware shell (C) 22,185 22,185 ±0
pkgs/pixie-6.1.0/pixie/fileformats/png.nim pixie 21,475 22,101 -626 (-2.8%)
fos_cloud.c.obj fos_* firmware shell (C) 19,651 19,258 +393 (+2.0%)
embedded_main.nim FrameOS core (Nim) 19,120 19,252 -132 (-0.7%)
x509_crt_bundle.S.obj mbedTLS + certificates 17,928 17,928 ±0
embedded_runtime.nim FrameOS core (Nim) 17,593 17,834 -241 (-1.4%)
nim/lib/pure/unicode.nim Nim stdlib 17,324 17,405 -81 (-0.5%)
frameos/utils/asset_colors.nim FrameOS core (Nim) 17,028 17,333 -305 (-1.8%)
lib/tz.nim FrameOS core (Nim) 16,589 16,722 -133 (-0.8%)
frameos/utils/status_screen.nim FrameOS core (Nim) 16,551 17,943 -1,392 (-7.8%)
nim/lib/pure/times.nim Nim stdlib 16,493 16,888 -395 (-2.3%)
ieee80211_ioctl.o Wi-Fi stack 15,592 15,588 +4 (+0.0%)

Flash = .text + .rodata from the linker map via esp_idf_size; "Inside each subsystem" splits every bucket one level down (the Nim core by directory, apps by app, packages by package, ESP-IDF by archive) over all objects, not just the largest. "String pool (attributed to efuse)" is the linker's merged string-literal pool for the whole image, not efuse code — see docs/esp32-image-size.md.

@mariusandra
mariusandra merged commit be112d1 into main Oct 18, 2026
22 of 23 checks passed
@mariusandra
mariusandra deleted the esp32-size-trim branch October 18, 2026 12:09
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.

1 participant