Repository navigation
Conversation
`messageRevision` was one counter per controller and part of the confirmed-window cache key. A write to any chat, a reaction, and every catch-up batch re-decoded the open chat's whole window on the main actor, at about 20 µs per row. Writes now report which chat and which message rows they touched. `noteMessageWrite` still bumps `messageRevision` for the views that observe it, and then: - leaves the cached window alone for a write to another chat - patches the written rows into the window for a write to the open chat, by binary search, and drops rows an arrival pushes out of the newest-N window - drops the window when a write's rows aren't known (reset resync, initial load, the notification-extension reload) A catch-up reports its writes once, when the run ends, not once per batch. `ConversationReactions.didPersist` now passes the chat and message ids.
A fresh read pulls an older row in to fill the limit, which the patch can't see.
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.
messageRevisionwas one counter per controller and part of the confirmed-window cache key. So an arrival in any chat, a reaction (ConversationReactions.didPersist), and each catch-up batch re-decoded the open chat's whole window on the main actor, at about 20 µs per row.Writes now report what they touched, as a
MessageWriteScope: every chat, one chat, or specific message rows in one chat.noteMessageWritestill bumpsmessageRevision, so the views that observe it re-evaluate as before. Then it handles the cached window by scope:newestWindowFloor(one indexedOFFSETread). When more than a quarter of the window was written, it re-reads the window instead.reloadFromDatabase. So does a write that removed a row from the newest-N window, since a fresh read would pull an older row in to fill the limit.A catch-up collects the rows from each batch and reports them once, in a
defer, so the error and reset paths report too.ConversationReactions.didPersistnow passes the chat and message ids.Trade-off: during a multi-batch catch-up,
unreadBelowCount,lastConfirmedMessage,hasMessagesand the jump badge read the DB directly but observemessageRevision, so they now update when the run ends rather than after each batch.Numbers
These come from the chat-load benchmark harness (
ChatLoadBenchmarkTests) on an iPhone 17 simulator (iOS 27.0), warm, withorigin/main641184f against this branch.hostedRereads(), open window of 1000 rows in a 2000-row chat. Each event is one write:The same holds for the 60-row window.
reactionFlow(), the main-actor cost of one reaction after the DB write. Before, that was a full window re-read. After, it's the patch insidedidPersist, and the re-read is a cache hit:The before and after columns are separate runs a few minutes apart, on a machine with a load average of 80 to 150. A separate earlier
origin/mainrun measured 20.46, 99.90 and 212.07 ms at 1000, 5000 and 10000 rows. The cost left after the patch grows with the window, likely from copying the cached array (inferred, not profiled).The extension write still misses, because the Darwin notification doesn't say which chats it wrote (see #1234).
Tests:
ConfirmedWindowPatchTestschecks the patched window against a freshmessages(conversationID:from:)/messagesWindowread on a temp database, after:At the controller level, it covers: