docs(tune): always check language, framework and recursion on hot paths

Every run now examines each measured hot path for the most efficient language and framework fit and for unnecessary recursion, and reports the result even when clean. Framework overhead joins the language section; changes stay bound to the session's limits.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Kevin Veen-BirkenbachandClaude Opus 5.5 committed 2026-11-01 00:47:22 +01:00
1 parent 8e19dbb960
commit 64403cefca
1 file changed
+31 -8
+31 -8
View File
@@ -22,8 +22,8 @@ suggestions, and allow free text:
1. **What to examine.** Suggestions: CI wall-clock, deploy duration, gate and
test runtime, image pulls and build caches, per-item loops and process
spawns, idempotency (work repeated on a second run), network round trips,
resource use (CPU, memory, disk, I/O), and language or runtime choice for
hot paths.
and resource use (CPU, memory, disk, I/O). Language, framework and
recursion are checked on every run anyway (see Always check).
2. **Which performance boundaries to keep.** Suggestions: time budgets per job,
deploy or gate; resource caps (memory, CPU, disk headroom); a minimum saving
per change (default 10 s per run); the measurement source that counts as
@@ -119,6 +119,23 @@ every agent session on this machine, not only the branch lineage.
- **A claim ends** when its holder reports the result, a proposal or an
abandoned attempt and releases it, or when the operator reassigns it.
## Always check
Every run examines these two on each measured hot path, whatever the operator
picked in the first question, and lists the result in the output table, a
clean result included:
- **Language and framework**: whether the hot path's language and framework
are the most efficient fit for its work (see Language and framework).
- **Unnecessary recursion**: a recursive function that recomputes the same
subproblem (memoize it or turn it into a loop), recursion that only walks a
list or a fixed depth (a loop), a tree walk that visits or reads the same
node more than once, depth that grows with the input (stack limits, Python's
1000 frames), and recursive tool calls: a make target calling make, a role
or playbook including itself, a script re-invoking itself per item. Count
the calls first (a profiler's call graph, cProfile's `ncalls`, log lines);
recursion that is bounded, rare and cheap stays.
## Levers that usually pay
- **Batch per-item process spawns**: N calls that each boot an interpreter or
@@ -133,16 +150,22 @@ every agent session on this machine, not only the branch lineage.
- **Overlap waits with work** only where concurrent execution is proven safe.
Schema migrations and lock-holding steps are usually not.
## Language and runtime
## Language and framework
Look for language optimizations where they make sense, for example replacing a
Python hot path with Rust:
Check the language and the framework of every measured hot path, for example
replacing a Python hot path with Rust, or a heavy framework layer with a
lighter one or the standard library:
- **Only for measured CPU-bound work.** When the profile shows the time in
computation inside the process (parsing, hashing, rendering, tight loops),
a compiled language can win by an order of magnitude. When the time goes to
process start-up, network round trips or waiting, batching in the current
language wins first, and a rewrite changes nothing.
- **Framework overhead**: when the profile puts the time inside the framework
(import and start-up, middleware, ORM query building, serialization),
compare a lighter framework or the standard library on the same input. An
ORM issuing one query per item is fixed by batching the query, not by
swapping the framework.
- **Prefer the narrowest cut**: rewrite the hot function as an extension
module (for Python and Rust: PyO3 and maturin) or a small binary behind the
same interface, before rewriting a whole tool.
@@ -151,9 +174,9 @@ Python hot path with Rust:
and test parity with the old implementation.
- **Prove it on a prototype**: the same input, the same machine state, a before
and an after number, and the old test suite passing against the new code.
- A language change is applied only when the session's limits allow new
languages or toolchains; otherwise it is submitted as a proposal with the
prototype's numbers.
- A language or framework change is applied only when the session's limits
allow new languages, frameworks or toolchains; otherwise it is submitted as
a proposal with the prototype's numbers.
## Delegating an optimization