Skip to content

Answer an attached viewer's unchanged listing without resending it - #888

Merged
SimonCropp merged 1 commit into
mainfrom
listing-generation
Sep 23, 2026
Merged

SimonCropp merged 1 commit into
mainfrom
listing-generation

Conversation

@SimonCropp

Copy link
Copy Markdown
Member

From the review's perf list: an attached viewer asks for the full listing five times a second, even while hidden. Each one is every patch base64'd twice by the owner, inside its gate, and parsed again by the viewer, almost always to learn that nothing changed.

The change

  • Tagged listings. The owner tags each full listing (ViewerResponse.Tag), and the viewer sends back the tag of the one it holds as the ListFull body.
  • Unchanged answers. While the tag still stands, the owner answers unchanged and sends nothing else. The viewer keeps the queue it already parsed. It still checks the tracked files each pass, since a re-run rewriting one changes no listing.
  • Order. The tag is taken before the listing is built. A change landing in between then costs one more full listing, never a stale listing kept under a newer tag.
  • Cheap tags. Both queues are immutable, so a new reference means a new generation.
    • The tray also folds in its tracked files, which its own scan changes, and a count of stashed window commands, so a focus is never answered as unchanged.
    • Each owner's tags carry an id of their own, so a tag held across an owner restart can't match.
  • Hidden windows list once a second instead of five times (OwnerLink.HiddenInterval).
  • Compatibility: older owners ignore the body and answer in full, and older viewers send no tag and get answered in full.

Tests

  • ViewerProtocolTests.AnUnchangedListingIsNotSentAgain covers the wire format: a matching tag, a changed tag, an untagged owner, and a reader that sends no tag.
  • AttachedViewerTests, against a real owning viewer over a socket:
    • AnUnchangedQueueIsNotSentAgain;
    • AnAttachedViewerFollowsAChangeAfterAnUnchangedListing;
    • ARefusalArrivesOnAnUnchangedListing: a send's message still reaches the window when the listing is unchanged.
  • TrayViewerSyncTest.ATrackedFileOrAStashedFocusIsNeverAnsweredUnchanged uses the real tray.
  • Three IpcTests snapshots gain Unchanged: false.

The full solution passes locally in Release: 2,046 passed, 24 skipped.

An attached viewer asks for the full listing five times a second, even hidden,
and a full listing is every patch base64'd twice by the owner, inside its gate,
then parsed again by the viewer - to learn, almost every time, that nothing
changed.

The owner now tags each full listing, and the viewer sends back the tag of the
one it holds. While the tag still stands the owner answers "unchanged" and
nothing else, and the viewer keeps the queue it already parsed; the tracked
files are still stat'd each pass, since a re-run rewriting one changes no
listing. The tag is taken before the listing is built, so a change landing in
between costs one more full listing rather than a stale one kept.

A tag is cheap to take: both queues are immutable, so a new reference is a new
generation. The tray also folds in its tracked files, which its own scan
changes, and a count of stashed window commands, so a focus is never answered
unchanged. Each owner's tags carry an id of their own, so a tag held across an
owner restart cannot match.

A hidden window lists once a second instead of five times.

Older owners ignore the tag and answer in full; older viewers send none and
are answered in full.
@SimonCropp
SimonCropp merged commit e993c22 into main Sep 23, 2026
8 of 9 checks passed
@SimonCropp
SimonCropp deleted the listing-generation branch September 23, 2026 04:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant