Skip to content

test(session-ui): benchmark incremental markdown projection - #59391

Open
dcerisano wants to merge 3 commits into
anomalyco:devfrom
dcerisano:markdown-projection-bench
Open

dcerisano wants to merge 3 commits into
anomalyco:devfrom
dcerisano:markdown-projection-bench

Conversation

@dcerisano

@dcerisano dcerisano commented Oct 26, 2026 •

Copy link
Copy Markdown

Issue for this PR

Refs #56202 (diagnosis), #55857 (prior implementation), #57016 (replacement).

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Adds benchmarks and regression tests for the streaming Markdown projection in packages/session-ui. No production code changes.

#57016 replaced the marked + remend projection with @opencode/patchmark. The benchmarks stream deterministic fixtures through project(previous, text, true) and record wall time, per-update latency, and patchmark's charsScanned. The tests cover projection behavior that patchmark's own suite does not assert: frozen-block identity, partition integrity, incremental-vs-full equivalence, blank-line splits across deltas, code-mode switching, and non-append fallbacks.

This is the surviving half of #55857. That PR targeted the removed marked path, so its implementation and the tests tied to it are gone.

Representative run (Ryzen Threadripper 1920X, Bun 1.4.2, 3 measured passes, medians). Baseline is f2735ef79b^, the commit before #57016, run through the same fixtures and timing loop:

Workload Baseline Current Speedup
many-paragraph-deltas 160.6 ms 4.6 ms 35.0×
one-long-paragraph (12.6 KB) 10,870.9 ms 118.0 ms 92.1×
completed-head-live-tail 263.8 ms 9.1 ms 29.1×
mixed-long-response 894.2 ms 16.8 ms 53.1×
growing-list 422.5 ms 5.2 ms 80.5×
growing-table 171.6 ms 2.6 ms 65.5×
open-code-fence 1.2 ms 4.6 ms 0.26×

The open-code-fence row is a measured regression of ~3.4 ms across 401 updates, reported rather than hidden. How the baseline was produced, the scaling sweep, and limitations are in packages/session-ui/performance/markdown-stream/README.md.

Provenance

  • Sep 11, 2026 — V1 fix #48432 opened.
  • Oct 10, 2026 — closed by thdxr: "If you think this is still relevant, please port it over and open it for V2." No review.
  • Oct 15, 2026 — V2 port #55857 opened. Benchmarks: 15.9× speedup (145.3 ms → 9.1 ms) and 114.3× speedup (10,565.2 ms → 92.5 ms). The opencode-agent review acknowledged "The speed-up is real" and asked for the split-delta fix.
  • Oct 16, 2026 — 37402d29 fixed the split-delta case; #56202 filed. The bot reproduced it the same day and noted "Your open PR fix(session-ui): optimize incremental markdown projection #55857 targets this path."
  • Oct 18, 2026 — final commit to #55857.
  • Oct 19–20, 2026 — #57016 did not exist until less than 72 hours after my final commit to #55857; it was then created, merged, and replaced the marked + remend path.
  • Oct 26, 2026 — #55857 closed as superseded; this PR carries the benchmarks and tests that still apply.

#57016's implementation is its own — no code was copied. The credit being asked for is the diagnosis (#56202) and the measurements, which predate #57016.

How did you verify your code works?

  • bun test src in packages/session-ui — 331 pass / 0 fail.
  • bun run typecheck:tsc in packages/session-ui — clean.
  • bunx oxlint on the changed files — 0 warnings / 0 errors.
  • Ran both benchmarks on this branch and on f2735ef79b^ for the baseline column.

Visual

No user-facing change.

Screenshots / recordings

None; no UI change.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

Add projection micro-benchmarks and regression coverage for the streaming
markdown projection layer now that @opencode/patchmark (anomalyco#57016) owns
incremental parsing.

The benchmarks stream deterministic fixtures through project() and record
wall time, per-update latency, and patchmark's charsScanned. The README
compares the patchmark path with the pre-anomalyco#57016 marked baseline on the
same fixtures.

The tests cover projection behavior that patchmark's own suite does not
assert directly: frozen-block identity, partition integrity, incremental
vs full projection, blank-line splits across deltas, and code-mode
switching.
@github-actions github-actions Bot added the needs:compliance This means the issue will auto-close after 2 hours. label Oct 26, 2026

@opencode-agent opencode-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No blocking problems. This adds tests and benchmarks only. I ran the new tests (59 pass), bun test src in packages/session-ui (331 pass), typecheck:tsc (clean) and both bench scripts. The scan counts and partition results match the README; the times were lower on my machine, as expected.

Public API: unchanged (tests and benchmark scripts only).

Worth fixing:

  • Several new tests are named after #55857's live-tail approach, where there was a cap and an "oversized tail" (see inline). The current project() just forwards to PatchmarkStream.update, so nothing has a cap. Please rename them to what they actually check, or drop them.
  • The scale.bench.ts header says per-delta work stays bounded, but its own output shows scanned characters growing with the square of the text length (see inline).
  • The README's "Marked baseline" column came from a harness with marked lexer counters that isn't in this PR, so nobody can regenerate it. Please either explain briefly how it was produced or keep only the current numbers.

})
})

test("boundedly re-lexes the live tail once it exceeds the cap", () => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no cap in the current project(): it forwards every update to PatchmarkStream.update. This test and the three "oversized tail" tests below carry over the names (and the 400–600-step loops) from #55857's approach, which no longer exists. As written, this one only checks that the blocks join back into the text and that at least one block is settled; the partition test further down already covers that. Could you rename these to the patchmark behavior they actually protect (for example, a blank line split across two deltas still splits the block), shrink the loops, and drop any that add nothing?

// Scaling sweep for `project()` in `src/components/markdown-stream.ts`.
//
// Streams one boundary-less paragraph of N words (one word per delta) and
// records total projection time plus the characters scanned by patchmark. The

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This says per-delta work stays bounded as the text grows. This script's own output contradicts that: charsScanned goes from 197,240 to 12,630,526 between 250 and 2,000 words, so it grows with the square of the length, as the README says. Please update the comment so it matches what the sweep measures.

Rename the live-tail tests to describe patchmark behavior instead of the
removed cap, shrink their loops, and state in the scale benchmark header
that a boundary-less line rescans the whole active line each delta.

Record how the marked baseline was produced so the README numbers can be
traced, and note that the baseline harness is not part of this PR.
@github-actions github-actions Bot removed the needs:compliance This means the issue will auto-close after 2 hours. label Oct 26, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Thanks for updating your PR! It now meets our contributing guidelines. 👍

@dcerisano

Copy link
Copy Markdown
Author

Addressed the review in d6ef2e5:

  • Renamed the four live-tail tests to the patchmark behavior they protect and shrank their loops (freezes completed paragraphs while the tail keeps growing, keeps a boundary-less paragraph in one live block, starts a new block when a blank line follows a long paragraph, splits blocks when blank-line separators arrive across deltas). Also renamed the two other marked-era test names.
  • Updated the scale.bench.ts header: a boundary-less paragraph is one active line, so scanned characters grow with the square of the length while wall time stays far below the baseline.
  • Added a paragraph to the README explaining that the marked baseline harness is not in this PR, how it was produced (f2735ef79b^ worktree, same fixtures and timing loop, lexer counters), and that the numbers are a one-off comparison.
  • Replaced the PR description with the repository template.

bun test src (331 pass), typecheck:tsc, and both benchmarks still pass.

@opencode-agent opencode-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both earlier points are fixed, plus the README baseline note. The leftover test names are now named after what they check, with shorter loops. The scale.bench.ts header matches what the sweep measures. The README now explains how the "Marked baseline" column was produced. Re-ran markdown-stream.test.ts (59 pass), bun test src (331 pass) and typecheck:tsc (clean). Nothing new to raise.

Public API: unchanged (tests and benchmark scripts only).

@opencode-agent opencode-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new commit only merges dev and doesn't change this PR's files. Both earlier points were fixed in the previous push. Re-ran markdown-stream.test.ts (59 pass) and typecheck:tsc (clean) on the merged head. Nothing new to raise.

Public API: unchanged (tests and benchmark scripts only).

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant