Tree-shaking: drop library code unreachable from -main (lever 3/4)
`jolt build --tree-shake` (or deps.edn :jolt/build {:tree-shake true}) does
reachability DCE over the re-emitted app + library namespaces: keep -main, every
side-effecting (non-def) top-level form, and every def reachable from those; drop
the rest. A macro (expanded at AOT, never called at runtime) is prunable too.
Sound: bails (keeps everything) if REACHABLE code resolves vars by name at runtime
(eval/resolve/ns-resolve/requiring-resolve/find-var/intern/load-string/...), which a
static call graph can't follow. Unreached eval-using library code is simply shaken
away and never triggers the bail. clojure.core and the compiler image stay baked
(prelude + image blobs), so only re-emitted namespaces are shaken for now.
The reachability machinery is in emit-image.ss (records: keep?/fqn/refs/str via
reduce-ir-children) + build.ss (BFS + bail check). build-smoke covers it (drops the
unreachable `twice` macro, output unchanged). Opt-in; default builds are untouched.
full make test green.
Scope note: this shakes the re-emitted app/lib code only. Measurement shows jolt's
compiled code is ~5.8MB of a ~9.8MB binary, dominated by the clojure.core prelude
(~1.5-2MB) and the compiler image (~0.8MB) — both baked blobs this pass doesn't
touch. Those (shake-core, drop-compiler-when-no-eval) are the larger footprint wins,
filed as follow-ups.
This commit is contained in:
parent
3e0fb805da
commit
75ac93689b
4 changed files with 139 additions and 10 deletions
|
|
@ -78,4 +78,18 @@ fi
|
|||
if ! grep -q '(jv\$app.util\$shout' "$out.build/flat.ss"; then
|
||||
echo " FAIL: --direct-link did not emit a direct app->app call"; exit 1
|
||||
fi
|
||||
echo "build smoke: passed (release + optimized + direct-link)"
|
||||
# Tree-shaking (opt-in): same result, and an unreachable def (the `twice` macro,
|
||||
# expanded at AOT and never called at runtime) is dropped.
|
||||
if ! JOLT_PWD="$app" bin/joltc build -m app.core -o "$out" --tree-shake >/dev/null 2>&1; then
|
||||
echo " FAIL: jolt build --tree-shake exited non-zero"; exit 1
|
||||
fi
|
||||
got_ts="$(cd / && "$out" alpha bb ccc 2>&1)"
|
||||
if [ "$got_ts" != "$want" ]; then
|
||||
echo " FAIL: --tree-shake binary output mismatch"
|
||||
echo "--- got ----"; echo "$got_ts"
|
||||
exit 1
|
||||
fi
|
||||
if grep -q 'def-var! "app.util" "twice"' "$out.build/flat.ss"; then
|
||||
echo " FAIL: --tree-shake did not drop the unreachable twice macro"; exit 1
|
||||
fi
|
||||
echo "build smoke: passed (release + optimized + direct-link + tree-shake)"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue