Reduce Turbopack cache size with per-family compression - #97714
Conversation
Co-authored-by: Luke Sandberg <210140+lukesandberg@users.noreply.github.com>
Tests PassedCommit: c55ba19 |
Stats from current PR🔴 3 regressions, 4 improvements
📊 All Metrics📖 Metrics GlossaryDev Server Metrics:
Build Metrics:
Change Thresholds:
⚡ Dev Server
📦 Dev Server (Webpack) (Legacy)📦 Dev Server (Webpack)
⚡ Production Builds
📦 Production Builds (Webpack) (Legacy)📦 Production Builds (Webpack)
📦 Bundle SizesBundle Sizes⚡ TurbopackClient Main Bundles
Server Middleware
Build DetailsBuild Manifests
Build Cache
📦 WebpackClient Main Bundles
Polyfills
Pages
Server Edge SSR
Middleware
Build DetailsBuild Manifests
Build Cache
🔄 Shared (bundler-independent)Runtimes
📝 Changed Files (33 files)Files with changes:
View diffsapp-page-exp..ntime.dev.jsfailed to diffapp-page-exp..time.prod.jsfailed to diffapp-page-tur..ntime.dev.jsfailed to diffapp-page-tur..time.prod.jsfailed to diffapp-page-tur..ntime.dev.jsfailed to diffapp-page-tur..time.prod.jsfailed to diffapp-page.runtime.dev.jsfailed to diffapp-page.runtime.prod.jsfailed to diffapp-route-ex..ntime.dev.jsDiff too large to display app-route-ex..time.prod.jsDiff too large to display app-route-tu..ntime.dev.jsDiff too large to display app-route-tu..time.prod.jsDiff too large to display app-route-tu..ntime.dev.jsDiff too large to display app-route-tu..time.prod.jsDiff too large to display app-route.runtime.dev.jsDiff too large to display app-route.ru..time.prod.jsDiff too large to display dev-validati..ntime.dev.jsfailed to diffdev-validati..ntime.dev.jsfailed to diffdev-validati..ntime.dev.jsfailed to diffdev-validati..ntime.dev.jsfailed to diffpages-api-tu..ntime.dev.jsDiff too large to display pages-api-tu..time.prod.jsDiff too large to display pages-api.runtime.dev.jsDiff too large to display pages-api.ru..time.prod.jsDiff too large to display pages-turbo...ntime.dev.jsDiff too large to display pages-turbo...time.prod.jsDiff too large to display pages.runtime.dev.jsDiff too large to display pages.runtime.prod.jsDiff too large to display server.runtime.prod.jsDiff too large to display use-cache-pr..ntime.dev.jsDiff too large to display use-cache-pr..ntime.dev.jsDiff too large to display use-cache-pr..ntime.dev.jsDiff too large to display use-cache-pr..ntime.dev.jsDiff too large to display 📎 Tarball URLCommit: fb436e2 |
This comment has been minimized.
This comment has been minimized.
Co-authored-by: Luke Sandberg <210140+lukesandberg@users.noreply.github.com>
Co-authored-by: Luke Sandberg <210140+lukesandberg@users.noreply.github.com>
|
Does that have an impact on binary size of the released *.node file, fleet? |
|
Measured on the released Linux x64 GNU artifact path ( The increase is mostly The PR stats |
Co-authored-by: Luke Sandberg <210140+lukesandberg@users.noreply.github.com>
Co-authored-by: Luke Sandberg <210140+lukesandberg@users.noreply.github.com>
Co-authored-by: Luke Sandberg <210140+lukesandberg@users.noreply.github.com>
Co-authored-by: Luke Sandberg <210140+lukesandberg@users.noreply.github.com>
Co-authored-by: Luke Sandberg <210140+lukesandberg@users.noreply.github.com>
Co-authored-by: Luke Sandberg <210140+lukesandberg@users.noreply.github.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
What?
Adds per-family compression configuration to
turbo-persistenceand configures the Turbopack filesystem cache according to each keyspace's access pattern:Each meta file records the family's compression algorithm as one explicit byte, which is validated against
FamilyConfigwhen the database opens. SST block and blob layouts remain unchanged.Why?
LZ4 decode performance is important for cache query latency, but using one codec for every keyspace leaves a substantial disk-size opportunity in
TaskData. The final split keeps Infra, TaskMeta, and TaskCache on the existing ordinary LZ4 path, whileTaskDataspends modestly more CPU to reduce persistent cache size.LZ4 HC4 was evaluated and removed before finalizing: across three real caches it made TaskMeta compression 4.24× slower for only 1.51% total cache-directory savings. Infra and TaskCache made no compression calls. Removing HC4 does not affect reads because HC4 and ordinary LZ4 use the same decoder.
How?
Real (tiny) Next.js cache A/B test
Final results after removing HC4, using three cold and five warm runs per workload:
test/e2e/filesystem-cachetest/e2e/app-dir/app-renderingtest/e2e/app-dir/client-reference-chunkingThe mixed warm result on the smallest fixture and apparent improvements elsewhere are treated as noise; combined measurements show no material write/read regression.
Temporary crate benchmark instrumentation
To demonstrate the cost of the retained codecs, temporary write/read benchmarks applied each codec to identical synthetic data. The benchmark code is not included in the final patch.
LZ4 HC4 was also evaluated during development: the same write benchmark took 256.31 ms (+571.7% vs LZ4), which motivated dropping it after the real-cache family breakdown showed little total-size benefit.
Native binary size
For Linux x64 GNU, using
build-native-releasefollowed by the release pipeline'sstrip -x:Removing HC4 saved 73,248 installed bytes versus the earlier PR state; replacing bincode framing with the explicit codec byte saved another 18,048 bytes. Together those review simplifications removed 91,296 installed bytes (24,420 gzip bytes) from the earlier branch state.
Vercel Site real application
Size
2.9G canary
2.2G this PR
a 25% savings!!!
Performance
Cold build (n=5), warm build (n=3), medians:
maxRSS converted at 1 GB = 2^30 bytes.
Looking at tracing data i see in a cold build
persistspan went from 5.06s duration using 63s cpu time to 6.04s using 73s cpu time, a ~20% regression. Which explains the cpu regression and the time progression.Because the time regression is in the
persistspan during shutdown the added latency is somewhat hidden.Of course we also see a small wall/user time regression in warm builds due to the extra decompression costs for zstd.