Optimize your code
This guide is the measured-optimization loop: use the graph to find where a codebase actually spends its time, change one thing, and prove — with a hard gate, not a hunch — that the change is safe and that it helped. It is the counterpart to the Static Analysis guide: that one answers structural questions by hand; this one closes the loop from measurement to a verified edit.
The same loop drives the /codespine-optimize agent.
Whether you run it yourself or hand it to the agent, the shape is identical:
Two rules hold the loop honest:
verifyis the gate, not the benchmark. The type-check + test result decides keep-or-revert. A benchmark delta is advisory — a noisy median that can suggest but never authorise a change.- Measure before you cut. Without a profile the graph can show you structure (what is central) but not cost (what is hot). Enrich first, or you are guessing.
Setup: build, then enrich
Optimization needs a graph that carries runtime weight. Build it (Getting Started has the full walk-through), then attach a profile.
# 1. build the semantic graph
npx codespine extract . --semantic
npx codespine load
# 2. record a V8 CPU profile while the code runs a representative workload
node --cpu-prof --cpu-prof-dir ./.codespine/prof ./run-workload.js
# 3. attach the measured self-time onto graph nodes (metadata.runtime)
npx codespine enrich ./.codespine/prof/*.cpuprofile --root .enrich joins each profiled frame to the declaration it belongs to and reports
the coverage — the fraction of profiled time that landed on a graph node.
Low coverage (most time in dependencies or native code) means the in-project
rankings below describe only a slice of the real cost; enrich says so plainly.
The sample projects wire this together:
npm run project01:enrichruns a profile-and-enrich script for you, andnpm run project01:tourwalks the whole loop end to end.
1. Find the leverage
Question: of everything in this codebase, what is worth optimizing?
Rank by measured self-time — the time spent in a node itself, the only thing a local rewrite can remove:
npx codespine hotspots --by self-time 1. 142 ms Method titleCase src/text/string_utils.ts:48
2. 91 ms Function normalizeWhitespace src/text/string_utils.ts:12
…hotspots ranks leverage; without a profile it falls back
to --by callers (static fan-in) and tells you so. The other metrics —
call-count, blast-radius — surface different kinds of leverage.
Self-time tells you where the time is spent; cost tells you
who is responsible for it. Inclusive cost is a node’s self-time plus everything
it transitively calls, so a cheap-looking function that calls an expensive one
still ranks high:
npx codespine cost # rank the whole graph by inclusive cost
npx codespine cost "$ID" # break one node into callee/caller attributionThe attribution view is the one to read before editing: it shows how much of a node’s cost flows into each callee (where to cut) and how much each caller is responsible for (who feels the change).
2. Scope a real target (optional)
Question: I have a vague wish (“make it faster”) — what is the concrete, measurable task?
The read-only /codespine-interview command turns a
dimension (latency, memory, cost, bundle size…) into a baseline-and-target task
grounded in real node ids, and hands it back to you. Use it when the goal is fuzzy;
skip it when you already know the symbol.
3. Make exactly one edit
Change one thing — by hand, or let /codespine-optimize
apply a single verified-safe edit. Before you touch a hot symbol, confirm its
blast radius the static way (references,
who-calls, blast-radius) so
you know exactly what a behaviour-preserving change must keep intact.
Keep the edit small and behaviour-preserving. The smaller the blast radius, the cheaper the next step is to trust.
4. Gate it with verify
Question: did the edit keep the code correct?
npx codespine verify --cwd .verify runs the project’s typecheck and test scripts and
returns one keep/revert verdict. ok: true → the edit stands; ok: false →
revert it (git restore <file>) and try another. When there is no test script it
degrades to type-check-only and reports that honestly — a type-check-only pass is
not a behaviour guarantee. This is the hard gate; nothing below overrides it.
5. Confirm the impact with benchmark
Question: did the edit actually make it faster?
npx codespine benchmark titleCase \
--workload ./bench/title_case_workload.ts --runs 5benchmark profiles the target over N runs and reports the
median + spread. Save a baseline before the edit and compare after:
# before the edit
npx codespine benchmark titleCase --workload … --save-baseline
# after the edit
npx codespine benchmark titleCase --workload … --baseline
# Δ vs baseline -57 ms (-40.1%) improvedRead the delta against the spread: a change smaller than the run-to-run spread is
noise, not a result. The benchmark is advisory — it informs you, it never
overrides the verify verdict from step 4.
6. Snapshot with report
Close the loop with a shareable record of where things stand:
npx codespine reportreport writes a CODEBASE_BRIEF whose Runtime section now
reflects your enriched, post-edit graph — a before/after you can diff or hand off.
What this loop can and cannot promise
verifyproves safety only as far as the tests reach. A green gate on a thin suite is a weak guarantee; the loop reports type-check-only passes as not behaviourally verified rather than dressing them up.benchmarkis a measurement, not a promise. Medians drift with machine load. Treat a sub-spread delta as “no measurable change”, and prefer a workload that mirrors production.- The graph sees static cost structure, profiles see dynamic cost. Hotspots and cost are only as representative as the workload you profiled — enrich with a realistic one, and watch the coverage number.
See also
hotspots·cost·enrich·benchmark·verify·report— the commands this loop chains.- Agent —
/codespine-optimizeruns this loop autonomously;/codespine-interviewscopes the target. - Static Analysis — the structural, drive-by-hand counterpart.
- Browse the Graph — get oriented before you optimize.