perf: memoize plugin loader alias maps#69316
Conversation
Greptile SummaryThis PR implements two startup-time performance optimizations: memoizing The only thing to verify is whether Confidence Score: 5/5Safe to merge; all remaining findings are P2 suggestions with no correctness or data-integrity impact. The memoization logic correctly covers all inputs to the underlying resolvers, and the new Slack entry point cleanly re-exports only the needed symbol. The only open question is whether channel-entry.ts is a live path that should also be updated — that is a follow-up improvement, not a blocker. extensions/slack/channel-entry.ts — still references the wide runtime-api.js barrel; worth confirming if this path is active.
|
cb1d934 to
11e3b49
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f9c19e35d1
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| aliasMapCache.set(cacheKey, result); | ||
| return result; |
There was a problem hiding this comment.
Cache the Jiti-normalized alias map, not the raw alias object
This memoization does not actually unlock Jiti’s normalizeAliases sentinel fast-path: Jiti tags the normalized clone with Symbol.for("pathe:normalizedAlias"), not the input alias object, so returning the same raw result reference here still causes re-normalization on each createJiti call. In practice, the startup-cost regression this commit targets remains, while we still introduce process-lifetime alias caching behavior. To make this optimization effective, the cached value needs to be the normalized alias object that already carries Jiti’s sentinel.
Useful? React with 👍 / 👎.
dc65601 to
7fac8da
Compare
buildPluginLoaderAliasMap() creates a new alias object via spread on every
call. jiti's normalizeAliases() uses a reference-identity sentinel
(`if (e[pt]) return e`) to skip its O(N²) normalization work — but fresh
object refs defeat the sentinel, causing the full cycle to repeat on
every call.
This change caches alias maps by their inputs (modulePath, argv1,
moduleUrl, pluginSdkResolution) so identical parameters return the same
object reference. Subsequent jiti calls hit the sentinel fast-path
instead of re-running normalization.
Includes 5 new tests covering:
- reference identity for identical inputs
- cache isolation (different modulePath, pluginSdkResolution, argv1
each produce distinct objects)
- content equivalence between cached and freshly-computed results
Refs #68983, #63948
7fac8da to
c5fc4ef
Compare
|
Thanks @amknight, landed via rebase merge. Landed on |
Summary
Why
OpenClaw hits this in real plugin/channel loader paths. A cached Jiti loader hit still had to rebuild the plugin SDK alias map and stringify the alias map into a Jiti cache key before it could discover that the loader was already cached.
Reading local
jiti@2.6.1source showed that this is not about reusing Jiti's internal alias sentinel across freshcreateJiti()calls. Jiti normalizes aliases into its own internal object. The useful optimization is avoiding repeated OpenClaw alias/config resolution before returning an already-cached loader.Measurements
Local synthetic measurements on this machine; medians across repeated samples.
buildPluginLoaderAliasMap()same module, 5,000 callsgetCachedPluginJitiLoader()same module, 5,000 callsloadChannelPluginModule()same module, 5,000 hot loadsTradeoff
This helps repeated same-context loader resolution: long-running processes, channel/package-state probes, runtime boundary loads, and import-heavy tests. It is not a broad cold-start win when every module path is unique. Unique paths still pay first-resolution cost, with cache entries capped to avoid retaining arbitrary module paths forever.
Verification
OPENCLAW_VITEST_MAX_WORKERS=1 pnpm test src/plugins/sdk-alias.test.ts src/plugins/jiti-loader-cache.test.tspnpm buildpnpm check