perf(CC-364): single streaming jq pass for pmctl trace tail - #546
Merged
Conversation
pmctl trace tail spawned two jq processes per event during the scan phase plus one more per row in the human emitter, making --all O(n) with a high constant (~20s / 338 events). Rework the scan as one jq -R streaming pass over the concatenated archive+active stream: it classifies each line (malformed / filtered-out / kept) and emits kept rows as "<ts>\t<line_no>\t<compact-json>", using jq's cumulative input_line_number as the global read-order tiebreaker for equal timestamps. Both emit helpers now stream through a single jq via cut -f3. Behavior is unchanged: same filters, inclusive lexicographic time window, malformed-row tolerance + "skipped N" warning, archive/active chronological merge, limit/--all semantics, compact-JSON byte identity. Drops the five module-global _PMCTL_TRACE_* vars and three now-dead scan helpers. New regression: 120+120 archive/active events with interleaved bands and two malformed rows, asserting count, non-decreasing merge order and the skip warning at a scale above the other cases (awk-generated fixtures). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KFPwSUfmLGh6KJLYFBArTS
pr-gate (qa-tester, 2x high/block) on the first draft of case_trace_large_partition_streaming: - F001: the "gzip unavailable -> pass; return 0" guard let a runner without gzip record the case as verified without running its archive coverage. Reworked the case to an active-file-only partition (240 events across three disjoint timestamp bands + two malformed rows), so it always executes; archive+active merge correctness stays covered by case_trace_active_archive_merge. - F002: added the harness-required Behavior/Steps docstring above the case; observable assertions unchanged. Focused: test-pmctl-trace.sh (13 passed), test-lint-test-docstrings.sh, shellcheck clean. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KFPwSUfmLGh6KJLYFBArTS
pr-gate round 2 was GO with one critic advisory (critic-F001, low): the scaled regression proves output correctness but nothing fails if per-event jq spawning returns. Add case_trace_tail_single_jq_pass: a counting jq shim on PATH tallies invocations across a 20-event and a 200-event run of `trace tail --all --json`; the test asserts the tallies are equal and non-zero (O(1) in event count). Streaming impl invokes jq once per run regardless of size; a per-event regression would make the 200-event tally ~10x the 20-event one. test-pmctl-trace.sh: 14 passed. shellcheck clean. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KFPwSUfmLGh6KJLYFBArTS
Index row -> done, body section gets a Closure 2026-08-27 (pr:#546) note and perf/parity evidence summary. validate.sh, test-pmctl-backlog, test-archive-closed-backlog, test-schema-task-mirrors-backlog all pass. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KFPwSUfmLGh6KJLYFBArTS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
CC-364 —
pmctl trace tailsingle streaming jq passProblem
pmctl trace tailspawned two jq processes per event in the scan phase(
jq -ctype check +jq -r @tsvfield extract) plus one more per row in thehuman emitter.
--allwas O(n) with a high constant — ~20s for 338 events.Change
Scan phase is now one
jq -Rstreaming pass over the concatenatedarchive + activestream. It classifies each line (malformed / filtered-out /kept) and emits kept rows as
<ts>\t<line_no>\t<compact-json>, using jq'scumulative
input_line_numberas the global read-order tiebreaker for eventssharing a timestamp. Both emit helpers stream through a single jq via
cut -f3.Measured: 400 events
--all --json~24s → 0.2s (~100x); jq invocationcount is now fixed (1 for
--json, 2 for human) regardless of event count.Behavior parity (unchanged)
--kind/--task/--subject/--idfilters, inclusive lexicographic--since/--untilwindow (empty ts excluded when bounded), malformed-rowtolerance +
trace: skipped N malformed row(s)warning, archive/activechronological merge,
-n/--limit/--limit 0/--allsemantics,compact-JSON byte identity. Drops the five module-global
_PMCTL_TRACE_*vars and three now-dead scan helpers.
Reuse note
pmctl-run-stats.sh(CC-358) has the same archive+activeevents.jsonlscanshape with a per-line jq spawn. Deliberately not refactored here — different
jq program + shell-side aggregation, out of CC-364 scope, and a shared
"event source" primitive would be a single-consumer abstraction until run-stats
is also converted. Left a pointer comment; no ticket exists yet for that
follow-up.
Tests
case_trace_large_partition_streaming— 240 active events across 3 disjointtimestamp bands + 2 malformed rows; asserts count, non-decreasing merge
order, skip warning. Active-only so it always executes.
case_trace_tail_single_jq_pass— countingjqshim on PATH; asserts theinvocation tally is equal (and non-zero) for a 20-event and a 200-event run,
i.e. O(1) in event count. Fault-sensitive: a per-event regression makes the
200-event tally ~10x the 20-event one.
test-pmctl-trace.sh14 passed; full suiterun-all-tests.sh105 passed,0 failed, 0 skipped.
PR-gate
3 rounds (round 1 NO-GO on two test-only qa-tester findings, rounds 2–3 GO;
rounds 2–3 sequential). Final round: critic / qa-tester / architecture /
security all approve, zero findings.
BACKLOG
CC-364 index row + body section marked
✅ donewith aClosure 2026-08-27 (pr:#546)note in this PR (docs(BACKLOG): mark CC-364 done).validate.sh,test-pmctl-backlog,test-archive-closed-backlog,test-schema-task-mirrors-backlogall pass.🤖 Generated with Claude Code