perf: migrate internal cache and index files to MessagePack serialization#10500
perf: migrate internal cache and index files to MessagePack serialization#10500
Conversation
|
cc @gluxon |
|
Interesting idea! I'll build this PR and run some performance benchmarks on our large monorepo. |
|
Pushed some more optimizations. Not all tests are fixed yet but I think it works now and can be benchmarked. |
81bc394 to
f7fe178
Compare
|
The results here ended up being surprising and I think there's something we missed in #10409. Using a hot cache and hot store, perf seems to be about the same before and after this PR on a large repo. This is the same repo I tested in #10409 (comment). Installs using MessagePack and JSON end up being around ~60s. However, I would have expected this to be in the ~30s range. This is how fast the same command takes on pnpm 10.28.0 and the commit right before switching to v8 buffers takes (d392c3d). I assumed commit da112f7 would make installs go back to the ~30 range, but that's not the case. It's still around ~60s. I'm going to look at CPU profile more deeply. Benchmarking MessagePackgit restore pnpm-lock.yaml
pnpm install --ignore-scriptsMessagePack (e841247)main (c494de3) |
|
That's weird. I was running my benchmarks on this package.json: https://github.com/pnpm/pnpm.io/blob/main/benchmarks/fixtures/alotta-files/package.json but I was only comparing before and after this change now. Wasn't comparing to v10. I use this script for testing hot cache: This one to test with cold cache: This is what I got with hot cache using pnpm v10: so according to my benchmarks this change improves performance by a lot. resuls with v8-file |
|
@gluxon how does this look like with your fix? |
|
I'll check now! For others following along, the performance regression I was seeing with pnpm v11 alpha and v10 should be fixed by #10502. |
There was a problem hiding this comment.
Pull request overview
Migrates pnpm’s internal store index files and metadata cache files from JSON serialization to MessagePack (via msgpackr) to improve install performance.
Changes:
- Introduce
@pnpm/fs.msgpack-fileutilities for MessagePack read/write and adopt them across the repo. - Switch store index files and metadata cache files to
.mpk, and update related readers/writers and CLI commands. - Replace object-based
PackageFiles*/SideEffects*shapes withMap-based representations and update tests accordingly.
Reviewed changes
Copilot reviewed 72 out of 73 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| worker/tsconfig.json | Adds reference to new msgpack fs package. |
| worker/src/start.ts | Reads/writes package index via msgpack and migrates file maps to Map. |
| worker/package.json | Adds @pnpm/fs.msgpack-file, removes load-json-file. |
| store/plugin-commands-store/tsconfig.json | Adds reference to msgpack fs package. |
| store/plugin-commands-store/src/storeStatus/index.ts | Reads integrity index as .mpk and adapts files to Map. |
| store/plugin-commands-store/package.json | Adds msgpack fs dep, removes load-json-file. |
| store/plugin-commands-store-inspecting/tsconfig.json | Adds reference to msgpack fs package. |
| store/plugin-commands-store-inspecting/test/findHash.ts | Updates expected index extension to .mpk. |
| store/plugin-commands-store-inspecting/src/findHash.ts | Reads .mpk indexes and iterates Map entries. |
| store/plugin-commands-store-inspecting/src/catIndex.ts | Reads .mpk package index files. |
| store/plugin-commands-store-inspecting/package.json | Adds msgpack fs dep, removes load-json-file. |
| store/package-store/tsconfig.json | Adds reference to msgpack fs package. |
| store/package-store/src/storeController/prune.ts | Prunes .mpk index files and uses Map accessors. |
| store/package-store/package.json | Adds msgpack fs dep, removes load-json-file. |
| store/cafs/test/index.ts | Updates CAFS tests to use Map for files. |
| store/cafs/src/readManifestFromStore.ts | Uses Map.get() for package.json entry. |
| store/cafs/src/index.ts | Updates exported CAFS types to new Map-based types. |
| store/cafs/src/getFilePathInCafs.ts | Changes CAFS index path suffixes to .mpk. |
| store/cafs/src/checkPkgFilesIntegrity.ts | Updates integrity checks to iterate Map-based structures. |
| store/cafs-types/src/index.ts | Removes raw record types; standardizes on Map types. |
| reviewing/plugin-commands-licenses/test/snapshots/index.ts.snap | Updates snapshot header link. |
| reviewing/license-scanner/tsconfig.json | Adds reference to msgpack fs package. |
| reviewing/license-scanner/test/getPkgInfo.spec.ts | Updates expected missing-index path to .mpk. |
| reviewing/license-scanner/src/getPkgInfo.ts | Reads .mpk indexes and adapts license scanning to Map. |
| reviewing/license-scanner/package.json | Adds msgpack fs dep, removes load-json-file. |
| resolving/npm-resolver/tsconfig.json | Adds reference to msgpack fs package. |
| resolving/npm-resolver/test/utils/index.ts | Updates retry helper to read .mpk metadata cache. |
| resolving/npm-resolver/test/resolveJsr.test.ts | Updates tests to read cached meta from .mpk. |
| resolving/npm-resolver/test/index.ts | Updates tests to read cached meta from .mpk. |
| resolving/npm-resolver/src/pickPackage.ts | Reads/writes cached registry metadata as .mpk. |
| resolving/npm-resolver/package.json | Adds msgpack fs dep; adjusts load-json-file usage for tests. |
| pnpm/tsconfig.json | Adds reference to msgpack fs package. |
| pnpm/test/utils/retryLoadJsonFile.ts | Removes JSON retry helper. |
| pnpm/test/utils/index.ts | Stops exporting removed JSON retry helper. |
| pnpm/test/install/misc.ts | Updates tests to read/write integrity indexes as .mpk and use Map. |
| pnpm/package.json | Adds @pnpm/fs.msgpack-file dependency. |
| pnpm-workspace.yaml | Adds msgpackr to catalog and allows msgpackr-extract build. |
| pnpm-lock.yaml | Locks msgpackr(+extract) and wires new workspace package. |
| pkg-manager/package-requester/tsconfig.json | Adds reference to msgpack fs package. |
| pkg-manager/package-requester/test/index.ts | Updates tests to read .mpk indexes and use Map. |
| pkg-manager/package-requester/src/packageRequester.ts | Renames package-dir index files to integrity*.mpk. |
| pkg-manager/package-requester/package.json | Adds msgpack fs dependency. |
| pkg-manager/headless/tsconfig.json | Adds reference to msgpack fs package. |
| pkg-manager/headless/test/index.ts | Updates side-effects cache tests for .mpk + Map structures. |
| pkg-manager/headless/package.json | Adds msgpack fs dependency. |
| pkg-manager/core/tsconfig.json | Adds reference to msgpack fs package. |
| pkg-manager/core/test/install/sideEffects.ts | Updates side-effects cache tests to use .mpk and Map. |
| pkg-manager/core/test/install/patch.ts | Updates patch tests to read .mpk index files and use Map. |
| pkg-manager/core/test/install/lockfileOnly.ts | Updates meta cache filename expectations to .mpk. |
| pkg-manager/core/package.json | Adds msgpack fs dependency. |
| modules-mounter/daemon/tsconfig.json | Adds reference to msgpack fs package. |
| modules-mounter/daemon/src/createFuseHandlers.ts | Reads .mpk indexes and uses Map.get() for file lookup. |
| modules-mounter/daemon/src/cafsExplorer.ts | Updates directory exploration helpers for Map-based files. |
| modules-mounter/daemon/package.json | Adds msgpack fs dep, removes load-json-file. |
| fs/msgpack-file/tsconfig.lint.json | Adds lint TS config for new package. |
| fs/msgpack-file/tsconfig.json | Adds build TS config for new package. |
| fs/msgpack-file/test/tsconfig.json | Adds test TS config for new package. |
| fs/msgpack-file/test/index.test.ts | Adds unit tests for msgpack read/write and Map/Set support. |
| fs/msgpack-file/src/index.ts | Implements msgpack read/write helpers using msgpackr. |
| fs/msgpack-file/package.json | Adds new workspace package definition. |
| fs/msgpack-file/README.md | Documents new msgpack fs utilities. |
| exec/plugin-commands-rebuild/tsconfig.json | Adds reference to msgpack fs package. |
| exec/plugin-commands-rebuild/test/index.ts | Updates rebuild tests for .mpk + Map sideEffects/files. |
| exec/plugin-commands-rebuild/src/implementation/index.ts | Reads .mpk indexes and checks sideEffects via Map. |
| exec/plugin-commands-rebuild/package.json | Adds msgpack fs dep, removes load-json-file. |
| cspell.json | Adds msgpack-related words to dictionary. |
| cache/commands/test/cacheList.cmd.test.ts | Updates cache list command tests for .mpk filenames. |
| cache/commands/test/cacheDelete.cmd.test.ts | Updates cache delete command tests for .mpk filenames. |
| cache/api/tsconfig.json | Adds reference to msgpack fs package. |
| cache/api/src/cacheView.ts | Reads cached meta from .mpk and updates glob patterns. |
| cache/api/src/cacheList.ts | Updates metadata file patterns to .mpk. |
| cache/api/package.json | Adds msgpack fs dep, removes load-json-file. |
| .changeset/msgpack-store-format.md | Declares major change: store/cache format switches to MessagePack. |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 72 out of 73 changed files in this pull request and generated 3 comments.
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 72 out of 73 changed files in this pull request and generated 1 comment.
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Seems a bit faster! I'm running: Commit d85ea8d Commit 3e7bebd Checking the CPU profile of these runs, most of the time is spent resolving dependencies and peers. Very little of the ~40s is spent deserializing MessagePack / JSON, so a |
|
Don't you test with an up-to-date lockfile? In that case resolution will be skipped. Otherwise it will be hard to see the difference. Alternatively, if you want to test with resolution, you can try |
|
In any case, it is a bit faster according to your benchmarks. Thanks for the confirmation! |
I did notice your benchmarks tested with Skipping resolution, we wouldn't benchmark deserialization of large cached package metadata.
I should have benchmarked with I still need a lockfile that's not up-to-date for this to force resolution and reads of |
Indeed. Thank you for this performance improvement! Always happy to help. |
|
I am doing some more changes to the format but it doesn't seem to make a difference in performance: #10504 |
install with hot cache/hot store (
pnpm i --ignore-scripts --offline --frozen-lockfile)this is with JSON:
this is with msgpackr:
this is with msgpackr+structured data+maps in index files:
install with cold cache (
pnpm i --ignore-scripts)this is with JSON:
this is with msgpackr+structured: