Speed up long chat buffer rendering#222
Open
leo-ar wants to merge 2 commits into
Open
Conversation
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.
First, thank you for building and maintaining the Emacs frontend. It has become
a very useful part of my workflow. This PR is an attempt to contribute back a
performance improvement for long-running chat buffers, with locally gathered
profiling/benchmark evidence included below to make the behavior easier to
evaluate.
I am also testing this branch in everyday Emacs/Pi usage. Thorough interactive
testing will take longer, but the early results look good enough that I wanted
to open the PR now so you can review the approach, tradeoffs, and implementation
while that real-world validation continues.
Summary
Speed up the Emacs chat renderer in two places where display-layer work was
repeated while buffers grow:
Batch history replay post-processing. During
pi-coding-agent--display-session-history, defer per-messagefontification/table decoration and run one consolidated pass after all
history has been inserted.
Avoid streaming table scans when no markdown pipe table is possible. During
assistant text streaming, only call
pi-coding-agent--maybe-decorate-streaming-tableafter a newline if recentstreamed text contained
|.This keeps live streaming/rendering behavior for actual markdown tables, while
avoiding tree-sitter table queries for ordinary prose/code deltas.
Motivation / evidence
Pi standalone does not show this slowdown; the bottleneck is in the Emacs
display/render layer.
History replay benchmark
To measure history replay, I used a locally saved long-running real session and
fed its messages through the Emacs history-rendering path. The benchmarked
session had 924 display messages, rendered to 322,947 chat-buffer characters,
and included 406 tool-call renderings. The benchmark compared the pre-change
behavior, which ran fontification/table decoration during each replayed message,
with the new batched behavior, which runs one consolidated post-processing pass
after replay.
Results:
An ELP profile of the legacy replay showed the expensive work was display
post-processing, not insertion/tool rendering:
Live streaming benchmark
To measure live growth, I preloaded the same real-session history into the Emacs
chat buffer, then simulated continuing the conversation with 200 ordinary
assistant text deltas containing prose/code-style markdown but no pipe tables.
This isolates the cost of the streaming table-detection path as the buffer grows
without depending on backend latency or model behavior.
Results:
Related upstream issues/PRs
Related but distinct from Keep following chat panes filled while output streams #201. That issue concerns tail-following windows
becoming visually underfilled while streaming; this PR targets repeated
display post-processing/tree-sitter table scans.
Adjacent to pi-coding-agent--treesit-table-regions: Query pattern is malformed #216 / Warn about incompatible Markdown grammars #218 because both involve markdown tree-sitter table
queries. This PR does not replace grammar compatibility checks; it reduces
unnecessary calls into the table-query path when no table is possible.
Similar motivation to Keep generic tool previews responsive while they stream #199, but a different path. Keep generic tool previews responsive while they stream #199 handled generic tool
preview streaming; this PR handles history replay and ordinary assistant text
deltas.
Tests
Added render unit coverage for:
messages with table-like content;
text_endbackstop scan.Validation run locally:
I also ran:
It failed on
pi-coding-agent-gui-test-table-resize-refreshes-hot-tail-onlywith:I checked the same single GUI test on a clean
upstream/masterworktree and itfailed identically in this environment, so I do not think this branch introduced
that failure.