Record selected performance approaches
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# Computational efficiency roadmap
|
||||
|
||||
Status: proposed; implementation has not begun.
|
||||
Status: proposed improvements; OD-1 and OD-2 resolved; implementation has not begun.
|
||||
|
||||
Date: 2026-10-09.
|
||||
|
||||
@@ -31,7 +31,7 @@ or promised speedups. Recheck the affected implementation before starting work.
|
||||
| PF-01 | PromptKit text reports are built even for YAML requests. | Render only the requested format and avoid redundant report buffers. | First pass |
|
||||
| PF-02 | Selected-command lookup scans a map; each ancestor is rediscovered from the root. | Direct declaration lookup and ancestry traversal proportional to path depth. | First pass |
|
||||
| PF-03 | Every invocation translates and sorts metadata; help and usage construct another backend tree. | Reuse immutable metadata and the invocation's prepared tree. | Measure and improve after the first pass |
|
||||
| PF-04 | Aggregate YAML framing splits every line and copies the complete native document. | Inspect only the opening lines; assess eliminating the complete framed copy. | Prefix scanning in the first pass; copying afterward |
|
||||
| PF-04 | Aggregate YAML framing splits every line and copies the complete native document. | Inspect only the opening lines and retain a complete framed buffer for delivery. | First pass |
|
||||
| PF-05 | Each registration copies the existing top-level registry. | Prepare new entries separately and install a validated batch atomically. | Lower priority |
|
||||
| PF-06 | Scope ordering, lookup, and selection repeat; selector duplicate checks scan previous entries. | Prepare stable scope metadata once and use direct duplicate checks. | Lower priority |
|
||||
|
||||
@@ -130,13 +130,14 @@ second backend construction also benefits a single CLI help or usage request.
|
||||
Measure both cases separately, including the cost of app construction and
|
||||
registration for consumers that execute only once.
|
||||
|
||||
Reusing mutable backend trees across different invocations is a later option,
|
||||
conditional on measured benefit and a clear account of state reset and value
|
||||
ownership. The first target can retain fresh backend parse state for each
|
||||
invocation. No public freeze step, backend selector, or concurrent-dispatch
|
||||
Under the selected OD-1 approach, construct fresh mutable backend parse state for
|
||||
each invocation, reuse that state within the invocation, and cache immutable
|
||||
metadata between invocations. Reusing mutable backend trees across invocations
|
||||
is deferred beyond this target. Measurements may motivate reconsidering it in
|
||||
future work. No public freeze step, backend selector, or concurrent-dispatch
|
||||
guarantee is needed for these improvements.
|
||||
|
||||
### PF-04: Reduce aggregate YAML scanning and copying
|
||||
### PF-04: Reduce aggregate YAML preamble scanning
|
||||
|
||||
In [configuration display](../../show.go), `hasYAMLDirective` and
|
||||
`frameEffectiveYAML` split the complete document into lines before examining its
|
||||
@@ -149,9 +150,11 @@ decision is complete. Share the resulting framing analysis where useful so
|
||||
directive detection and scope-label placement do not independently scan the same
|
||||
preamble. Avoid a document-wide line index and unnecessary string conversions.
|
||||
|
||||
Then evaluate delivering separators, labels, and native byte segments directly,
|
||||
retaining one native render buffer without a second complete framed copy. Keep
|
||||
the design simple enough to preserve failure handling for multiple writes.
|
||||
Under the selected OD-2 approach, retain the native render buffer and assemble a
|
||||
complete framed buffer for each document before delivery. This keeps delivery
|
||||
and write-failure handling straightforward. The full document copy remains an
|
||||
accepted cost of this target; the optimization removes the document-wide line
|
||||
index and redundant preamble scanning.
|
||||
|
||||
Preserve native bytes, directive placement, inline document content and block
|
||||
scalars, scope-label escaping, and boundary newlines according to the CLI
|
||||
@@ -207,14 +210,16 @@ preparing this metadata.
|
||||
1. Establish focused before-change measurements for PF-01, PF-02, and PF-04,
|
||||
then implement conditional formatting, direct command lookup/ancestry, and
|
||||
YAML prefix scanning as independently reviewable changes.
|
||||
2. Measure complete dispatch paths and implement PF-03's reuse within an
|
||||
invocation and immutable metadata preparation where the benefit justifies
|
||||
the coordination and retained memory.
|
||||
3. Evaluate PF-04's segmented delivery, PF-05, and PF-06 using the first-pass
|
||||
evidence and expected consumer sizes. Record a deferral if a proposed change
|
||||
adds complexity without a worthwhile benefit.
|
||||
4. Consider backend reuse across invocations only if the remaining measured cost
|
||||
warrants it.
|
||||
2. Measure complete dispatch paths, then implement PF-03's reuse within an
|
||||
invocation and immutable metadata caching. Compare the resulting runtime
|
||||
gains with the coordination cost and retained memory.
|
||||
3. Evaluate PF-05 and PF-06 using the first-pass evidence and expected consumer
|
||||
sizes. Record a deferral if a proposed change adds complexity without a
|
||||
worthwhile benefit.
|
||||
4. Record remaining costs after the selected improvements. Mutable backend reuse
|
||||
across invocations and segmented YAML delivery remain future possibilities
|
||||
beyond this target; any reconsideration should use the measurements and a
|
||||
deliberate change to the selected approach.
|
||||
|
||||
Use Go benchmarks with controlled, offline fixtures when implementation work is
|
||||
authorized. Keep external loading and service latency out of isolated CommandKit
|
||||
@@ -264,45 +269,46 @@ ownership, and replacing Cobra are outside this target. They require their own
|
||||
concrete motivation and review rather than following automatically from a
|
||||
performance optimization.
|
||||
|
||||
## Open Decisions
|
||||
## Resolved Decisions
|
||||
|
||||
The first-pass formatting, lookup, and prefix-scanning changes have a clear
|
||||
recommended direction. Two broader implementation choices remain dependent on
|
||||
performance evidence. Resolve them when preparing the corresponding work; they
|
||||
do not require a public API change.
|
||||
The following approaches were selected on 2026-10-09. Both are implementation
|
||||
choices within the existing public contracts. No significant open decisions
|
||||
remain for this roadmap's scope.
|
||||
|
||||
### OD-1: How far should backend reuse extend?
|
||||
|
||||
**Recommendation:** Initially reuse the prepared backend within one invocation
|
||||
and cache immutable metadata between invocations, while constructing fresh
|
||||
mutable backend state for each `Execute`. This removes repeated help/usage work
|
||||
and metadata translation while keeping invocation isolation straightforward.
|
||||
Measure the remaining backend construction cost before expanding reuse. This is
|
||||
the recommended PF-03 target, not a permanent restriction on implementation.
|
||||
**Selected approach:** Adopt the recommended approach: reuse the prepared backend
|
||||
within one invocation and cache immutable metadata between invocations, while
|
||||
constructing fresh mutable backend state for each `Execute`.
|
||||
|
||||
**Alternative:** Retain a mutable backend tree per `App` and reset it before each
|
||||
invocation. This can remove more command and flag-set construction work for
|
||||
consumers that execute repeatedly. It also retains more memory and requires
|
||||
**Reasoning:** This removes repeated help/usage work and metadata translation
|
||||
while keeping invocation isolation straightforward. Measure the remaining
|
||||
backend construction cost to inform future work. The selection defines the
|
||||
PF-03 target without establishing a permanent architectural restriction.
|
||||
|
||||
**Alternative considered:** Retain a mutable backend tree per `App` and reset it
|
||||
before each invocation. This can remove more command and flag-set construction
|
||||
work for consumers that execute repeatedly. It also retains more memory and requires
|
||||
careful reset of parsed values, presence, operands, contexts, streams, and other
|
||||
backend state, plus refresh after registration. Choose it if measurements show
|
||||
that the remaining construction cost warrants the added lifecycle complexity
|
||||
and behavioral evidence establishes independent invocations. A CLI that executes
|
||||
only once receives little benefit from this additional reuse.
|
||||
backend state, plus refresh after registration. The added lifecycle complexity
|
||||
is deferred until measurements justify reconsideration and behavioral evidence
|
||||
establishes independent invocations. A CLI that executes only once receives
|
||||
little benefit from this additional reuse.
|
||||
|
||||
### OD-2: How much buffering should aggregate YAML retain?
|
||||
|
||||
**Recommendation:** After prefix scanning is improved, favor retaining the native
|
||||
render buffer and delivering framing and native slices as separate segments if
|
||||
measurements confirm a useful memory reduction. This removes the second complete
|
||||
document copy while keeping native rendering complete before that document's
|
||||
delivery begins. The work includes correct accounting for cancellation and
|
||||
partial output across segment writes, without changing aggregate acquisition
|
||||
timing. Compare allocation savings with any additional writer-call overhead.
|
||||
**Selected approach:** Adopt the previously listed alternative: retain the
|
||||
complete framed buffer after replacing the line splits with prefix scanning.
|
||||
|
||||
**Alternative:** Retain a complete framed buffer after replacing the line splits
|
||||
with prefix scanning. This keeps delivery simple and avoids additional writes
|
||||
for each document. It still allocates and copies the document a second time,
|
||||
which matters for large reports. Prefer it if representative documents are small
|
||||
or segmented delivery provides insufficient benefit to justify its extra error
|
||||
handling. Either choice can deliver PF-04's initial prefix-scanning improvement;
|
||||
record the selected buffering approach and its evidence.
|
||||
**Reasoning:** This keeps delivery simple and avoids additional writes for each
|
||||
document. It accepts the second document allocation and copy while removing the
|
||||
line index and unnecessary scanning. Measure the resulting allocation cost,
|
||||
particularly for large reports, without making segmented delivery part of this
|
||||
implementation target.
|
||||
|
||||
**Alternative considered:** Retain only the native render buffer and deliver
|
||||
framing and native slices as separate segments. This can reduce peak allocation
|
||||
and copying while keeping native rendering complete before delivery. It requires
|
||||
accounting for cancellation and partial output across segment writes and may
|
||||
increase writer-call overhead. It remains a viable future optimization if the
|
||||
selected approach's measured memory cost warrants the additional delivery logic.
|
||||
|
||||
Reference in New Issue
Block a user