Summary
After upgrading to 2026.4.21, openclaw status, openclaw plugins list, and other CLI commands that touch the plugin loader regressed from ~instant to 12–20s wall time on a machine with 65/99 plugins loaded. CPU profile shows normalizeAliases in node_modules/jiti/dist/jiti.cjs consuming ~85% of runtime (10.3s of 12.2s total).
Environment
- openclaw 2026.4.21 (f788c88)
- macOS 26.4.1 arm64, node 25.8.1
- 65/99 plugins loaded (most are bundled providers)
Repro
time openclaw gateway status > /dev/null
# 12.1s total, 18.5s user CPU
Root cause
src/plugins/jiti-loader-cache.ts memoizes the per-plugin aliasMap object (via cachedPluginSdkScopedAliasMaps), but the loader still calls createJiti(filename, { alias: aliasMap, ... }) per plugin. Inside Jiti, normalizeAliases(alias) is O(n²) over the alias keys and is NOT cached across calls (only self-memoizes via a hidden symbol on its own return object, which openclaw never feeds back in). With 65 plugins × O(n²) over the SDK subpath alias map, this dominates startup.
Top of CPU profile (status command):
self_ms % function
10351 84.5% normalizeAliases jiti.cjs
273 2.2% createJiti jiti.cjs
Related: 2026.4.20 release notes mention "reuse plugin loader alias and Jiti config resolution across repeated same-context loads" — but the fix only covered the openclaw-side aliasMap cache, not Jiti's per-createJiti normalization cost.
Workaround / fix
Content-/identity-keyed cache around normalizeAliases. Local WeakMap patch (5-line diff in jiti.cjs) drops status time from 12.1s → 1.6s (≈7× faster). Prototype diff:
var __jitiNAWM = globalThis.__jitiNAWM ||
(globalThis.__jitiNAWM = new WeakMap());
function normalizeAliases(e) {
if (e[pt]) return e;
var c = __jitiNAWM.get(e); if (c) return c;
// ... existing body ...
__jitiNAWM.set(e, t);
return Object.defineProperty(t, pt, {value:!0,enumerable:!1}), t;
}
Better fix lives in openclaw: wrap createJiti in getCachedPluginJitiLoader so identical (filename, aliasMap, tryNative) triples share the Jiti instance cross-plugin, or pass the normalized aliasMap in and have Jiti short-circuit via its existing pt marker.
Related
Summary
After upgrading to 2026.4.21,
openclaw status,openclaw plugins list, and other CLI commands that touch the plugin loader regressed from ~instant to 12–20s wall time on a machine with 65/99 plugins loaded. CPU profile showsnormalizeAliasesinnode_modules/jiti/dist/jiti.cjsconsuming ~85% of runtime (10.3s of 12.2s total).Environment
Repro
Root cause
src/plugins/jiti-loader-cache.tsmemoizes the per-plugin aliasMap object (viacachedPluginSdkScopedAliasMaps), but the loader still callscreateJiti(filename, { alias: aliasMap, ... })per plugin. Inside Jiti,normalizeAliases(alias)is O(n²) over the alias keys and is NOT cached across calls (only self-memoizes via a hidden symbol on its own return object, which openclaw never feeds back in). With 65 plugins × O(n²) over the SDK subpath alias map, this dominates startup.Top of CPU profile (status command):
Related: 2026.4.20 release notes mention "reuse plugin loader alias and Jiti config resolution across repeated same-context loads" — but the fix only covered the openclaw-side aliasMap cache, not Jiti's per-createJiti normalization cost.
Workaround / fix
Content-/identity-keyed cache around
normalizeAliases. Local WeakMap patch (5-line diff injiti.cjs) drops status time from 12.1s → 1.6s (≈7× faster). Prototype diff:Better fix lives in openclaw: wrap
createJitiingetCachedPluginJitiLoaderso identical(filename, aliasMap, tryNative)triples share the Jiti instance cross-plugin, or pass the normalized aliasMap in and have Jiti short-circuit via its existingptmarker.Related