Skip to content

Enable the V8 compile cache in bin/run to cut CLI startup time (~1.2s on slow hosts) #90

@Rinse12

Description

@Rinse12

Problem

Every CLI invocation re-parses and re-compiles the CLI's own module graph: the ~600 files under dist/, @oclif/core, and the rest of the dependency closure. On a production server (slow host, Node v22.22.2) this costs about 1.2s of every command, measured while decomposing time bitsocial community list (see the breakdown in pkc-js docs/protocol/import-performance.md, "Decomposition of the remaining ~5.5s"):

Layer Median (steady state)
bare node -e 0 ~0.05s
import("@pkcprotocol/pkc-js") alone ~1.8s
command graph (list.js -> BaseCommand -> pkc-js) ~2.5s (~0.7s CLI dist on top of pkc-js)
oclif boot (bitsocial --version) ~0.5s

pkc-js already enables the compile cache for its own graph: its npm import entry calls module.enableCompileCache() and then dynamic-imports the real graph. But that only covers modules compiled after the call. Everything the CLI loads before reaching pkc-js (its own dist/ files, oclif, other deps) is compiled first, uncached, on every run.

Proposed fix

Call enableCompileCache() at the very top of bin/run, before importing @oclif/core. bin/run already delays oclif behind a dynamic import (for DEBUG stripping), so the whole framework + command graph compiles after the cache is on:

#!/usr/bin/env node

// Enable the V8 compile cache before anything is imported so the CLI's own dist/,
// oclif and all deps get bytecode-cached across invocations (no-op on Node < 22.8).
const { enableCompileCache } = await import("node:module");
enableCompileCache?.();

// ... existing DEBUG stripping ...

const oclif = await import("@oclif/core");

Notes:

  • module.enableCompileCache() exists since Node 22.8; the optional call keeps older Node working (no-op).
  • Default cache dir is os.tmpdir()/node-compile-cache, overridable with NODE_COMPILE_CACHE, opt-out with NODE_DISABLE_COMPILE_CACHE=1.
  • First run after an upgrade pays a small one-time cache-population cost; every later run skips parse/compile for the whole graph.

Validation

On a slow host, compare time bitsocial --version (oclif boot only) and time bitsocial community list before/after, second-and-later runs. Expected: most of the ~1.2s CLI-graph share recovered; pkc-js numbers unchanged (it caches itself already).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions