Repository navigation
perf(command-code): measure fragmented NDJSON incrementally - #8277
Conversation
|
No actionable comments were generated in the recent review. Walkthrough
Merge Risk:
|
|
✅ Deterministic PR hygiene checks passed. |
✅ READY
Review readiness checklist
✅ 4/4 boxes ticked. This pull request is already Ready for Review. Hygiene✅ Deterministic PR hygiene checks passed. |
Ingwannu
left a comment
There was a problem hiding this comment.
Approving head c1b809270011a70fc58a4f058e59cdcd2440098f (full diff, 3 files).
Checked:
src/adapters/command-code.tsndjson(): the invariantbufferBytes === utf8Bytes(buffer)holds on every path.TextDecoder(streaming) only emits complete code points and maps invalid/incomplete-at-EOF input to U+FFFD, so the UTF-8 size ofbuffer + decodedis exactlybufferBytes + utf8Bytes(decoded); when no newline arrives the buffer is unchanged after the append, so skipping the remeasure is exact, and the drained residual is remeasured only when lines were removed.- The "retained suffix has no newline" guard is sound: after each drain loop
buffercontains no\n, so only newly decoded text can complete a record. - #8047's ordering is preserved:
resizeBuffer(which can throw on overflow) still runs beforebuffer += decoded, the single live charge is resized by delta, andfinallyreleasesbufferBytes. Event order, the suspendedyield*during draining, EOF flush and cancellation are unchanged. - Tests: the work-bound cases exercise the real adapter for newline- and EOF-terminated 64 KiB records in 256-byte reads and assert intact output, zero retained bytes, and linear encode/scan volume; the EOF U+FFFD cases pin replacement-byte admission at 2 (refused) and 3 (admitted) bytes. The author's parent-run and mutation results show the bounds fail on the quadratic variants.
structure/transports/byte-accounting.mdmatches the new behavior.- Hosted CI on this exact head: Cross-platform CI
gates,test changed,structure gateandcigreen; Catalog async contracts green.devhas not touchedcommand-code.ts, its tests or the structure doc since the base883bf0fd7d.
Non-blocking: when a fragment does contain a newline, buffer.indexOf("\n") still rescans the retained prefix once (it could start at the pre-append length), but that is one pass per newline-bearing read and stays within the asserted bound.
Summary
Command Code's NDJSON reader UTF-8 encodes the entire growing buffer twice per read and searches the retained incomplete line again even when the new fragment contains no newline. For a record arriving as n fixed-size fragments, this repeats quadratic measurement/allocation and newline-search work. In the real adapter, a 65,568-byte ASCII record delivered in 256-byte reads causes 16,908,320 encoded bytes; an EOF-terminated 65,567-byte record causes 17,105,020.
Measure only each newly decoded fragment, add its byte size to the retained total, and search for newlines only when the new decoded text contains one. After draining complete lines, remeasure only the remaining suffix. The same probes now encode exactly 65,568 and 65,567 bytes respectively, with intact output and zero retained bytes on completion. This makes that fragmented-record bookkeeping linear; it is not an end-to-end latency or process-RSS measurement.
Duplicate search covered open and closed issues/PRs for Command Code NDJSON, incremental accounting, quadratic work, TextEncoder, fragmented buffers and NDJSON encoding. No equivalent fix was found. Merged #8047 fixes duplicate budget charges and explicitly leaves asymptotic scanning unchanged; this patch preserves that fix. Closed #4389 concerns other adapters/shared Chat and SSE paths and does not change command-code.ts. #2531/#2532 concern non-record JSON validation. This implementation is independent.
Verification
Exact head:
c1b809270011a70fc58a4f058e59cdcd2440098f. Base:devat883bf0fd7d6ef7a208223ffd363705ba387d13ad. Native Windows, Bun 1.4.4. Refetched upstream before submission: 1 ahead / 0 behind. The tree has not changed since validation.bun test tests/providers/command-code-buffer-budget.test.ts --timeout 30000: 10 passed / 2 failed, 38 assertions. Both new work-bound cases failed at the encoding-volume assertion (16,908,320 and 17,105,020 measured characters); intact output and cleanup assertions passed.bun test --isolate tests/providers/command-code-buffer-budget.test.ts tests/providers/command-code-provider.test.ts tests/providers/command-code-error-finish.test.ts tests/providers/command-code-tool-text.test.ts tests/providers/command-code-tool-text-prose-split.test.ts tests/ci-workflows/file-size-ratchet.test.ts --timeout 30000: 166 passed / 0 failed, 40,778 assertions. Covers provider/tool behavior, whole/one-byte Unicode reads, exact/over-limit budgets, shared ownership, drain-before-read, consumer return, cancellation and unchanged file-size caps.bun run typecheck: passed, no type errors in 2,330 files.bun run structure:check: passed.bun run privacy:scan: passed.git diff --check, staged whitespace check before commit, andgit diff upstream/dev...HEAD --check: passed. Working tree clean.Full-suite scope exception: the full local suite and broad import-connected
test:changedwere not run. This adapter imports OAuth, dispatch and shared bridge surfaces, so that run is disproportionate to the bounded private NDJSON-loop change on this Windows laptop. Five focused Command Code files plus the file-size gate were run explicitly. Broader integration/platform coverage remains for repository CI; no hosted CI success is claimed. No workflow dispatch or rerun was initiated, and regression fixtures use no live provider credentials or inference.Applied test-design-guard to work-volume, Unicode/EOF boundaries and cleanup checks.
Author review: regression sensitivity
Rechecked the runtime diff, retained-byte ownership, split UTF-8 decoding, EOF flush and newline/EOF record handling on the same exact head. No additional runtime defect was found.
Two independent temporary mutations were tested with
bun test tests/providers/command-code-buffer-budget.test.ts --test-name-pattern 'bounds fragmented NDJSON' --timeout 30000:encoder.encode(buffer + decoded).byteLengthpreserves admission values but restores cumulative-prefix allocation. Both cases failed the encoding-work assertion: 8,486,944 > 262,272 and 8,552,510 > 262,268 measured characters.finally, with SHA-256 verification after each run. Neither mutation is committed. The committed source and tests remain unchanged, so the existing passing validation above still applies; no broad suite was repeated.Checklist
Review readiness checklist
This PR stays in draft until every box below is ticked. Tick all four boxes once the requirements are met:
Required local validation passed; commands, results, and any full-suite exception are documented.
I pushed my PR to a recent dev commit (at most 10 behind; a maintainer may still ask for the exact tip before merge).
I resolved all correct Codex and CodeRabbit findings.
My PR is ready for review.
Summary by CodeRabbit
Maintainer integration verification
I am integrating this PR into
devunder the maintainer-integration policy without a second maintainer approval. Independent review of headc1b809270011a70fc58a4f058e59cdcd2440098ffound no issues; no review threads or maintainer objections were open at inspection.ci,gates,test changed, and the applicable Ubuntu jobs. The full five-shard matrix and platform-specific jobs were filtered by PR policy. Catalog async contracts, attempt 2 passed.devat1b87631d51c2547fe4e061e771cf3f46114ba269applied cleanly and passed the same 220-test focused/guard set, typecheck, privacy scan, and structure check. The temporary merge was discarded afterward.