Skip to content

CI: Nim test nimcache as immutable snapshots (shard 1 red on main) - #568

Merged
mariusandra merged 1 commit into
mainfrom
ci-nimcache-snapshots
Oct 18, 2026
Merged

mariusandra merged 1 commit into
mainfrom
ci-nimcache-snapshots

Conversation

@mariusandra

Copy link
Copy Markdown
Collaborator

Shard 1 of the Nim tests fails to link on main and on every PR since this morning, with no code at fault:

@m..@s..@sapps@sdata@sclock@sapp_loader.nim.c:(.text+0x542): undefined reference to `eqdup___OOZconfig_u2307'

(main 39118817269 and #567 identical; main 39118507287 the same kind in test_refresh_interval.)

Cause. Nim reuses a module's object file when the C it generates equals the .c on disk and the .o is newer (shouldRecompile, compiler/cgen.nim). Nothing checks that the .o came from that .c. The warm cache was one shared directory per shard on /mnt/cache. Overlapping runs copied into it (rsync -a) and out of it (cp -a) at the same time, so a restore could pair one build's .c with another build's newer .o. Nim linked the stale object, and the if: always() save after the run wrote the pair back for every later run. The workflow comment assumed "Nim validates each object by hash anyway"; it doesn't.

Fix. frameos/tools/ci_nimcache.sh restore|save <shard>:

  • A save writes a new snapshot. It uses rsync --link-dest on the snapshot this job restored, so unchanged files are hardlinks and a save costs only what the run rebuilt. Then it swaps shard-N.current in one rename. Snapshots are never modified after that.
  • A restore resolves the symlink once and copies that one snapshot.
  • Replaced snapshots stay for 30 min, for restores still copying, then get pruned. A partial copy can only miss files, which costs a recompile, never a wrong pairing.
  • Hardlinks come only from the job's own restored snapshot. rsync's quick check is size+mtime, and everything the job wrote is newer than that snapshot. Linking against a snapshot another run just published could take a same-size object compiled in the same second.
  • No save on a cancelled job: a gcc killed mid-write leaves a truncated .o newer than its .c.
  • New path (nimcache/frameos-tests-snapshots): one cold build per shard, and the poisoned pairs are left behind.

Tested in a Linux container: three savers doing restore → rebuild 8 of 40 test dirs → save cycles against four restorers for 30 s. 227 restores, 0 with a test dir mixing two builds. Hardlinking and the round trip are checked too. The previous scheme under the same load: 250 of 266 restores mixed, and the shared dir itself ended up holding a mixed pair. Shellcheck clean.

Host disk: 56 G free on monster; the first snapshots take ~17 G. The old nimcache/frameos-tests/shard-{1..8} dirs (~31 G, shards 5–8 unused since the move to four shards) can be deleted once branches carry this (noted in tools/gha-runners/README.md). I haven't touched them.

🤖 Generated with Claude Code

…not mix it

Shard 1 failed to link on three runs in a row, main included
(`undefined reference to eqdup___OOZconfig_u2307` in test_runner_loop,
`eqdup___OOZjs95runtimeZapp95runtime_*` in test_refresh_interval), with no
code at fault. Nim reuses a module's object file when the C it generates
equals the .c on disk and the .o is newer (shouldRecompile in
compiler/cgen.nim); nothing checks that the .o came from that .c. The warm
cache was one shared directory per shard that overlapping runs copied
into (rsync) and out of (cp -a) at the same time, so a restore could take
one build's .c and another build's newer .o. Nim linked the stale object,
and the save after it wrote the pair back for every later run.

frameos/tools/ci_nimcache.sh keeps each shard's cache as snapshots written
once and never changed. A save rsyncs into a new snapshot with
--link-dest on the snapshot the job restored (unchanged files become
hardlinks, so a save costs only what the run rebuilt), then swaps a
`current` symlink in one rename. A restore resolves the symlink once and
copies that snapshot. Replaced snapshots live 30 minutes for restores
still copying. Hardlinks follow rsync's size + mtime check, so they come
only from the job's own restored snapshot, which every file the job wrote
is newer than. The cache moves to a new path, which also drops the
poisoned pairs. The save is skipped on a cancelled job: a gcc killed
mid-write leaves a truncated .o newer than its .c.

Stress-tested in a Linux container: three savers doing restore, rebuild,
save cycles against four restorers for 30 s, 227 restores, none with a
test dir mixing two builds. The old scheme under the same load: 250 of
266 restores mixed, and the shared directory itself ended up holding
a mixed test dir, the pair every later run would have linked.

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

Copy link
Copy Markdown
Contributor

ESP32 firmware size

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

Image This PR v2026.10.15 Δ
esp32-s3 app (OTA image) 3,154,224
87.5% of 3520K slot, 440 KB free
3,138,272 +15,952 (+0.5%)
esp32-s3 merged flash image 3,219,760 3,203,808 +15,952 (+0.5%)
esp32-s3-32mb app (OTA image) 3,154,224
76.4% of 4032K slot, 952 KB free
3,138,272 +15,952 (+0.5%)
esp32-s3-32mb merged flash image 3,285,296 3,269,344 +15,952 (+0.5%)

Breakdown by subsystem — esp32-s3

Subsystem This PR v2026.10.15 Δ
FrameOS core (Nim) 487,875 477,042 +10,833 (+2.3%)
QuickJS 360,345 360,373 -28 (-0.0%)
pixie 304,382 304,354 +28 (+0.0%)
Wi-Fi stack 295,296 295,304 -8 (-0.0%)
Nim stdlib 251,547 251,436 +111 (+0.0%)
FrameOS apps (Nim) 190,404 190,356 +48 (+0.0%)
ESP-IDF misc 181,395 181,564 -169 (-0.1%)
Embedded font 146,362 146,362 ±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,519 132,439 +80 (+0.1%)
lwIP / HTTP / WebSocket 126,779 126,800 -21 (-0.0%)
libc / libm / newlib 116,263 116,263 ±0
Storage (SPIFFS / FatFS / SD / NVS) 94,108 94,080 +28 (+0.0%)
Nim packages (chrono, zippy, chroma, qrgen, ...) 71,933 71,849 +84 (+0.1%)
Display drivers (C) 64,962 64,946 +16 (+0.0%)
Crypto (monocypher) 35,141 35,141 ±0
Total mapped flash 3,132,541 3,116,676 +15,865 (+0.5%)
Inside each subsystem

FrameOS core (Nim) — 487,875

Part This PR v2026.10.15 Δ
frameos/js_runtime 118,440 115,444 +2,996 (+2.6%)
frameos/utils 117,350 112,401 +4,949 (+4.4%)
frameos/interpreter.nim 99,980 100,264 -284 (-0.3%)
embedded_main.nim 19,252 19,252 ±0
embedded_runtime.nim 17,830 17,834 -4 (-0.0%)
lib/tz.nim 16,722 16,722 ±0
frameos_nim_glue.c.obj 11,455 10,635 +820 (+7.7%)
frameos/planner.nim 9,689 9,681 +8 (+0.1%)
frameos/event_loop.nim 8,412 8,412 ±0
frameos/types.nim 7,909 7,909 ±0
frameos/values.nim 7,699 7,699 ±0
frameos/single_scene_host.nim 6,687 6,712 -25 (-0.4%)
frameos/apps.nim 6,585 6,585 ±0
frameos/spool.nim 5,787 5,787 ±0
frameos/input_state.nim 5,079 3,766 +1,313 (+34.9%)
embedded_scene.nim 4,945 4,945 ±0
frameos/events_gen.nim 3,926 3,948 -22 (-0.6%)
fos_netguard.c.obj 3,532 2,179 +1,353 (+62.1%)
frameos/app_config.nim 2,939 2,935 +4 (+0.1%)
frameos/reboot_reason.nim 2,648 2,648 ±0
frameos/node_config.nim 2,618 2,618 ±0
frameos/app_capabilities.nim 2,489 2,489 ±0
frameos/events.nim 2,410 2,410 ±0
frameos/refresh_interval.nim 1,635 1,639 -4 (-0.2%)
frameos/runtime_diagnostics.nim 767 767 ±0
frameos/event_log.nim 415 431 -16 (-3.7%)
fos_version.c.obj 328 328 ±0
frameos/cloud — 255 -255 (-100.0%)
frameos/channels.nim 152 152 ±0
frameos/ids.nim 137 137 ±0
frameos/hal 44 44 ±0
frameos/retired_apps.nim 14 14 ±0

QuickJS — 360,345

Part This PR v2026.10.15 Δ
quickjs.c.obj 287,826 287,846 -20 (-0.0%)
libunicode.c.obj 50,178 50,178 ±0
libregexp.c.obj 13,995 13,999 -4 (-0.0%)
dtoa.c.obj 5,681 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 — 304,382

Part This PR v2026.10.15 Δ
pixie/fontformats/opentype.nim 55,460 55,460 ±0
pixie/fileformats/webp.nim 37,493 37,493 ±0
pixie/fileformats/svg.nim 36,975 36,983 -8 (-0.0%)
pixie/paths.nim 32,895 32,875 +20 (+0.1%)
pixie/fileformats/jpeg.nim 29,424 29,436 -12 (-0.0%)
pixie/fileformats/png.nim 22,097 22,101 -4 (-0.0%)
pixie/images.nim 15,771 15,779 -8 (-0.1%)
pixie/fonts.nim 10,995 10,995 ±0
pixie/paints.nim 9,869 9,869 ±0
pixie/fileformats/bmp.nim 8,286 8,258 +28 (+0.3%)
pixie/common.nim 7,389 7,413 -24 (-0.3%)
pixie/blends.nim 6,528 6,516 +12 (+0.2%)
pixie/fileformats/gif.nim 5,957 5,965 -8 (-0.1%)
pixie/inflatestream.nim 5,233 5,233 ±0
pixie.nim 5,220 5,224 -4 (-0.1%)
pixie/fileformats/webp_vp8_tables.nim 3,881 3,881 ±0
pixie/fileformats/ppm.nim 3,729 3,713 +16 (+0.4%)
pixie/contexts.nim 3,050 3,054 -4 (-0.1%)
pixie/fileformats/qoi.nim 2,726 2,702 +24 (+0.9%)
pixie/internal.nim 754 754 ±0
pixie/rgb565.nim 385 385 ±0
pixie/fontformats/svgfont.nim 215 215 ±0
pixie/decodebudget.nim 50 50 ±0

Wi-Fi stack — 295,296

Part This PR v2026.10.15 Δ
libnet80211.a 136,164 136,168 -4 (-0.0%)
libpp.a 62,154 62,154 ±0
libwpa_supplicant.a 54,900 54,904 -4 (-0.0%)
libphy.a 34,176 34,176 ±0
libesp_wifi.a 4,780 4,780 ±0
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 — 251,547

Part This PR v2026.10.15 Δ
pure/collections/tables.nim 72,312 72,312 ±0
system.nim 48,509 48,457 +52 (+0.1%)
pure/unicode.nim 17,405 17,405 ±0
pure/times.nim 16,884 16,888 -4 (-0.0%)
pure/json.nim 13,722 13,722 ±0
std/private/dragonbox.nim 10,351 10,351 ±0
pure/strutils.nim 8,043 8,047 -4 (-0.0%)
pure/parsexml.nim 6,003 6,011 -8 (-0.1%)
pure/algorithm.nim 5,372 5,372 ±0
pure/base64.nim 5,290 5,290 ±0
pure/hashes.nim 4,181 4,181 ±0
pure/xmlparser.nim 3,555 3,555 ±0
pure/parsejson.nim 3,553 3,553 ±0
std/formatfloat.nim 3,500 3,504 -4 (-0.1%)
pure/uri.nim 3,225 3,225 ±0
pure/streams.nim 2,820 2,820 ±0
pure/strformat.nim 2,546 2,546 ±0
std/syncio.nim 2,339 2,355 -16 (-0.7%)
pure/collections/sets.nim 2,075 2,075 ±0
pure/xmltree.nim 2,047 2,047 ±0
pure/lexbase.nim 1,801 1,801 ±0
pure/parseutils.nim 1,750 1,750 ±0
system/exceptions.nim 1,598 1,598 ±0
pure/strtabs.nim 1,572 1,572 ±0
pure/pathnorm.nim 1,336 1,336 ±0
pure/options.nim 1,016 1,016 ±0
std/private/ospaths2.nim 994 994 ±0
pure/collections/lists.nim 979 979 ±0
pure/math.nim 841 841 ±0
pure/collections/deques.nim 822 822 ±0
pure/random.nim 696 696 ±0
std/private/digitsutils.nim 651 651 ±0
std/oserrors.nim 633 633 ±0
std/private/osdirs.nim 572 572 ±0
system/dollars.nim 529 529 ±0
std/monotimes.nim 501 406 +95 (+23.4%)
std/private/oscommon.nim 329 329 ±0
std/envvars.nim 250 250 ±0
std/private/decode_helpers.nim 240 240 ±0
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
std/assertions.nim 87 87 ±0
core/macros.nim 65 65 ±0
system/ctypes.nim 9 9 ±0

FrameOS apps (Nim) — 190,404

Part This PR v2026.10.15 Δ
apps/data/icalJson 50,745 50,733 +12 (+0.0%)
apps/render/calendar 30,942 30,874 +68 (+0.2%)
apps/data/localImage 10,432 10,432 ±0
apps/render/split 9,736 9,772 -36 (-0.4%)
apps/data/eventsToAgenda 9,068 9,068 ±0
apps/render/zoomPan 8,600 8,648 -48 (-0.6%)
apps/apps.nim 7,255 7,247 +8 (+0.1%)
apps/render/text 5,447 5,455 -8 (-0.1%)
apps/data/xmlToJson 5,428 5,428 ±0
apps/render/svg 5,264 5,192 +72 (+1.4%)
apps/render/image 4,696 4,708 -12 (-0.3%)
apps/logic/setAsState 3,477 3,453 +24 (+0.7%)
apps/data/rotateImage 3,461 3,465 -4 (-0.1%)
apps/data/downloadImage 3,313 3,325 -12 (-0.4%)
apps/render/gradient 3,205 3,229 -24 (-0.7%)
apps/data/qr 3,118 3,122 -4 (-0.1%)
apps/data/downloadUrl 3,053 3,053 ±0
apps/render/color 2,836 2,824 +12 (+0.4%)
apps/data/newImage 2,668 2,668 ±0
apps/data/resizeImage 2,558 2,558 ±0
apps/render/opacity 2,312 2,296 +16 (+0.7%)
apps/data/log 2,299 2,299 ±0
apps/data/prettyJson 2,225 2,225 ±0
apps/data/clock 1,871 1,875 -4 (-0.2%)
apps/data/parseJson 1,848 1,856 -8 (-0.4%)
apps/logic/nextSleepDuration 1,663 1,663 ±0
apps/logic/ifElse 1,494 1,494 ±0
apps/logic/breakIfRendering 1,390 1,394 -4 (-0.3%)

ESP-IDF misc — 181,395

Part This PR v2026.10.15 Δ
libesp_hw_support.a 37,632 37,632 ±0
libhal.a 21,869 21,865 +4 (+0.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,756 7,756 ±0
libconsole.a 5,733 5,733 ±0
libjson.a 4,940 4,940 ±0
libesp_driver_gpio.a 3,890 3,878 +12 (+0.3%)
libbootloader_support.a 3,817 3,813 +4 (+0.1%)
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,253 3,253 ±0
libesp_driver_ledc.a 3,054 3,054 ±0
libesp_mm.a 2,451 2,451 ±0
libapp_update.a 2,426 2,414 +12 (+0.5%)
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,362

Part This PR v2026.10.15 Δ
assets/fonts.nim 146,362 146,362 ±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,519

Part This PR v2026.10.15 Δ
libmbedcrypto.a 71,379 71,291 +88 (+0.1%)
libmbedtls.a 45,799 45,799 ±0
libmbedx509.a 7,084 7,092 -8 (-0.1%)
libesp-tls.a 6,705 6,705 ±0
libesp_https_server.a 1,552 1,552 ±0

lwIP / HTTP / WebSocket — 126,779

Part This PR v2026.10.15 Δ
liblwip.a 78,385 78,445 -60 (-0.1%)
libhttp_parser.a 10,350 10,350 ±0
libesp_http_server.a 10,020 10,020 ±0
libtcp_transport.a 8,241 8,245 -4 (-0.0%)
libespressif__esp_websocket_client.a 6,818 6,822 -4 (-0.1%)
libesp_http_client.a 6,666 6,666 ±0
libesp_netif.a 6,299 6,252 +47 (+0.8%)

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,108

Part This PR v2026.10.15 Δ
libspiffs.a 20,380 20,380 ±0
libfatfs.a 20,133 20,133 ±0
libspi_flash.a 14,168 14,168 ±0
libnvs_flash.a 13,705 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,964 1,956 +8 (+0.4%)
libesp_vfs_console.a 678 678 ±0
libnvs_sec_provider.a 5 5 ±0

Nim packages (chrono, zippy, chroma, qrgen, ...) — 71,933

Part This PR v2026.10.15 Δ
QRgen 3.1.0 22,056 22,060 -4 (-0.0%)
chrono 0.3.1 15,658 15,586 +72 (+0.5%)
zippy 0.10.19 15,216 15,200 +16 (+0.1%)
chroma 1.0.0 14,714 14,714 ±0
checksums 0.2.1 3,371 3,371 ±0
flatty 0.3.4 533 533 ±0
jsony 1.1.5 272 272 ±0
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 +5,079 5,079 —
pkgs/QRgen-3.1.0/QRgen/renderer.nim -3,780 — 3,780
frameos/js_runtime/app_runtime.nim +2,216 74,851 72,635
frameos/utils/http_client.nim +1,815 11,805 9,990
frameos_nim_glue.c.obj +820 11,455 10,635
fos_client.c.obj +691 12,957 12,266
frameos/js_runtime/burrito.nim +603 8,097 7,494
esp_efuse_utility.c.obj +595 135,683 135,088
fos_cloud.c.obj +393 19,651 19,258
frameos/interpreter.nim -284 99,980 100,264
fos_ota.c.obj +172 5,639 5,467
fos_settings.c.obj +104 7,722 7,618
pkgs/chrono-0.3.1/chrono.nim +72 15,658 15,586
apps/render/calendar/app_loader.nim +68 7,125 7,057
fos_scenes.c.obj -63 7,515 7,578
Largest 30 objects
Object Subsystem This PR v2026.10.15 Δ
quickjs.c.obj QuickJS 287,826 287,846 -20 (-0.0%)
assets/fonts.nim Embedded font 146,362 146,362 ±0
esp_efuse_utility.c.obj String pool (attributed to efuse) 135,683 135,088 +595 (+0.4%)
frameos/interpreter.nim FrameOS core (Nim) 99,980 100,264 -284 (-0.3%)
frameos/js_runtime/app_runtime.nim FrameOS core (Nim) 74,851 72,635 +2,216 (+3.1%)
nim/lib/pure/collections/tables.nim Nim stdlib 72,312 72,312 ±0
pkgs/pixie-6.1.0/pixie/fontformats/opentype.nim pixie 55,460 55,460 ±0
libunicode.c.obj QuickJS 50,178 50,178 ±0
nim/lib/system.nim Nim stdlib 48,509 48,457 +52 (+0.1%)
apps/data/icalJson/ical.nim FrameOS apps (Nim) 45,028 45,016 +12 (+0.0%)
pkgs/pixie-6.1.0/pixie/fileformats/webp.nim pixie 37,493 37,493 ±0
pkgs/pixie-6.1.0/pixie/fileformats/svg.nim pixie 36,975 36,983 -8 (-0.0%)
frameos/utils/image.nim FrameOS core (Nim) 35,946 35,942 +4 (+0.0%)
pkgs/pixie-6.1.0/pixie/paths.nim pixie 32,895 32,875 +20 (+0.1%)
monocypher.c.obj Crypto (monocypher) 31,916 31,916 ±0
frameos/js_runtime/runtime.nim FrameOS core (Nim) 31,662 31,686 -24 (-0.1%)
pkgs/pixie-6.1.0/pixie/fileformats/jpeg.nim pixie 29,424 29,436 -12 (-0.0%)
apps/render/calendar/app.nim FrameOS apps (Nim) 23,817 23,817 ±0
fos_http.c.obj fos_* firmware shell (C) 22,185 22,185 ±0
pkgs/pixie-6.1.0/pixie/fileformats/png.nim pixie 22,097 22,101 -4 (-0.0%)
fos_cloud.c.obj fos_* firmware shell (C) 19,651 19,258 +393 (+2.0%)
embedded_main.nim FrameOS core (Nim) 19,252 19,252 ±0
frameos/utils/status_screen.nim FrameOS core (Nim) 17,947 17,943 +4 (+0.0%)
x509_crt_bundle.S.obj mbedTLS + certificates 17,928 17,928 ±0
embedded_runtime.nim FrameOS core (Nim) 17,830 17,834 -4 (-0.0%)
nim/lib/pure/unicode.nim Nim stdlib 17,405 17,405 ±0
frameos/utils/asset_colors.nim FrameOS core (Nim) 17,333 17,333 ±0
nim/lib/pure/times.nim Nim stdlib 16,884 16,888 -4 (-0.0%)
lib/tz.nim FrameOS core (Nim) 16,722 16,722 ±0
pkgs/pixie-6.1.0/pixie/images.nim pixie 15,771 15,779 -8 (-0.1%)

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 af94e40 into main Oct 18, 2026
22 checks passed
@mariusandra
mariusandra deleted the ci-nimcache-snapshots branch October 18, 2026 12:08
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