Skip to content

build: enable safe ICF to shrink the binary#34478

Merged
nathanwhit merged 2 commits into
denoland:mainfrom
nathanwhit:enable-safe-icf
May 29, 2026
Merged

build: enable safe ICF to shrink the binary#34478
nathanwhit merged 2 commits into
denoland:mainfrom
nathanwhit:enable-safe-icf

Conversation

@nathanwhit

@nathanwhit nathanwhit commented May 28, 2026

Copy link
Copy Markdown
Member

Enables safe identical code folding (ICF) at link time. Rust emits a large number of identical machine-code functions (monomorphized drop glue, Debug impls, closures, generic instantiations); folding the identical copies shrinks the binary.

What

  • macOS aarch64 and Linux (x86_64 + aarch64): lld --icf=safe
    • mac via .cargo/config.toml; Linux via the CI RUSTFLAGS/RUSTDOCFLAGS in ci.ts
  • Windows (MSVC): /OPT:ICF, non-debug only (rustc already enables /OPT:REF,ICF for optimized builds; set explicitly to make it durable)
  • (x86_64 macOS intentionally excluded — it doesn't use lld.)

--icf=safe only folds functions whose addresses are not significant (via address-significance tables), so function-pointer identity is preserved.

Numbers (aarch64-apple-darwin, release, stripped, full cargo build)

no-ICF ICF Δ
stripped binary 84.83 MB 81.06 MB −3.77 MB (−4.4%)
__text 53.7 MB 49.7 MB −4.0 MB

Deterministic (static section sizes), measured via a real full build — the way the binary ships.

Note on idle RSS

ICF's idle-RSS effect is ~1 MB (within noise); this change is justified by binary size, not RSS. (An earlier revision of this description claimed larger RSS and size wins — both were measurement artifacts: incremental-build layout noise for RSS, and a cargo rustc relink folding __const ~2.3MB more than a full build for size. The numbers above are the corrected, full-build values.)

@nathanwhit nathanwhit enabled auto-merge (squash) May 29, 2026 00:25
@nathanwhit nathanwhit changed the title perf: enable safe ICF (identical code folding) when linking build: enable safe ICF to shrink the binary May 29, 2026
@nathanwhit nathanwhit merged commit 8db0265 into denoland:main May 29, 2026
137 checks passed
jdalton added a commit to SocketDev/socket-btm that referenced this pull request Jun 1, 2026
Apply the link-time Identical Code Folding optimization from
[deno#34478](denoland/deno#34478) where it
actually fits node-smol's toolchain.

ICF folds byte-identical functions at link time. Deno measured ~4.4% on
a Rust binary via lld --icf=safe; the technique is linker-level, so it
ports to node-smol's C++ output. Mapping it to the real per-platform
linkers:

- Windows (MSVC link.exe): set OptimizeReferences + EnableCOMDATFolding
  (/OPT:REF + /OPT:ICF) on the Release VCLinkerTool. Release implies these
  already; making them explicit keeps the behavior durable, matching the
  durability fix Deno made for its MSVC path. Debug keeps incremental
  linking untouched.
- macOS (ld64/ld-prime): already folds in release; no flag needed.
- Linux (bfd ld): node-smol never selects gold or lld, and bfd has no
  ICF. Getting it there needs a linker switch, deferred pending a
  measurement that justifies the toolchain risk.

Assessment + measurement recipe documented in
packages/node-smol-builder/docs/binary-size-icf.md.
zanieb added a commit to astral-sh/uv that referenced this pull request Jun 9, 2026
Inspired by denoland/deno#34478

Use `--icf=safe` for optimized macOS release artifacts, via Rust's
bundled Mach-O LLD.

Measurements showed useful size wins on macOS; Linux did not show a
meaningful artifact-size improvement and are excluded here. See
#19615 (comment)
littledivy pushed a commit to crowlKats/deno that referenced this pull request Jun 10, 2026
…#34478)

Enables **safe identical code folding (ICF)** at link time across
platforms. Rust emits a large number of identical machine-code functions
(monomorphized `drop` glue, `Debug` impls, closures, generic
instantiations); folding the identical copies shrinks the binary and
lowers resident memory.

### What

- **macOS (aarch64 + x86_64)** and **Linux (x86_64 + aarch64)**: `lld
--icf=safe`
- mac via `.cargo/config.toml`; Linux via the CI
`RUSTFLAGS`/`RUSTDOCFLAGS` in `ci.ts` (CI sets `RUSTFLAGS`, which
overrides `config.toml`, and guarantees `lld`)
- **Windows (MSVC)**: `/OPT:ICF`, scoped to non-debug builds (rustc
already enables `/OPT:REF,ICF` for optimized builds; set explicitly to
make it durable)

`--icf=safe` only folds functions whose addresses are *not* significant
(via address-significance tables), so function-pointer identity is
preserved — unlike `--icf=all`.

### Numbers (measured on `aarch64-apple-darwin`, `release` profile)

| metric | before | after | Δ |
|---|---|---|---|
| stripped binary (`strip -x -S`) | 84.83 MB | 78.84 MB | **−5.99 MB
(−7.0%)** |
| `__TEXT` segment | 80.6 MB | 74.7 MB | −6.2 MB |
| idle RSS (`Deno.serve` idle, median of 6) | ~60.6 MB | ~54.6 MB |
**−6.0 MB (~10%)** |

Idle RSS measured via `Deno.memoryUsage().rss` after a 1s settle;
spreads were tight (±0.3 MB), so the delta is well clear of noise.

### Notes

- Numbers above are arm64 macOS. The same mechanism applies on the other
platforms; exact savings will vary (fat-LTO/CGU=1 release already folds
some duplicates, but ICF still folds more — the win held and even grew
vs. `release-lite` in testing).
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