Repository navigation
Conversation
…ne stamp read Every message write rebuilt the list with three kinds of read: getLatestVisibleForAllChats once through the preview stream, the same query again inside buildFeedFromDb, and getUnreadSeq once per chat for the READ pointer's stamp. - The preview query now takes its chat ids from chat_metadata instead of SELECT DISTINCT chat_id_hex FROM chat_messages, which walked an index over every stored message. The list builds only from metadata rows, so a chat whose messages have no metadata row was never shown; the query now leaves it out as well. - buildFeedFromDb uses the previews the stream already read. Until the stream's first emission it reads them itself, so first paint is unchanged. - getUnreadSeqs reads every row's stamp in one statement per 400 keys, a VALUES list joined to chat_messages on its primary key. 400 keys is 800 bind variables, under the 999 of the platform SQLite at minSdk. The paged feed and stageReadStamps still read one stamp at a time; they run per sync, not per message. FeedObservedPreviewTest checks the streamed and direct builds produce the same list and that a preview change does not query the previews again. ChatMessageDaoTest covers the metadata-less chat, getUnreadSeqs against getUnreadSeq across more keys than one statement takes, and the query plan's primary-key lookup.
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.
Every message write rebuilt the conversation list with three kinds of read:
getLatestVisibleForAllChatsthrough the preview stream, the same query again insidebuildFeedFromDb, andgetUnreadSeqonce per chat for the READ pointer's stamp. At 1,000 chats that was 1,000 stamp queries per incoming message.chat_metadata. It took its chat ids fromSELECT DISTINCT chat_id_hex FROM chat_messages, which walks an index over every stored message. It now reads them fromchat_metadata. The list only builds from metadata rows, so a chat with messages but no metadata row was never shown; the query now leaves it out too.buildFeedFromDbuses the previews the stream already emitted. Until the stream's first emission it reads them itself, so first paint is unchanged.getUnreadSeqsreads every row's stamp in one statement per 400 keys: aVALUESlist joined tochat_messageson its primary key. 400 keys is 800 bind variables, under the 999 of the platform SQLite at minSdk.The paged feed and
stageReadStampsstill read one stamp at a time. They run once per sync, not once per message.The preview stream now also re-runs on
chat_metadatawrites, because Room invalidates by table. The re-run is cheap now, anddistinctUntilChangedstops it from rebuilding the list. One difference from before: achat_metadatawrite can reachcombineahead of the preview stream's re-run, so one build can pair that chat's new metadata with its previous preview. The next emission corrects it, and the settled list is the same as before.code/cashnever did this because it re-read the previews on every build.Numbers
ChatArrivalBenchmarkTest.arrival, 1000 chats × 1000 messages, host JVM. Second (warm) run of each scenario, from the write to the last observer settling:code/cashbuildFeedFromDbalone, (a)The harness doesn't call
FeedSyncDelegate. It modelsbuildFeedFromDbwith DAO calls, so on this branch that model was changed to match the new code: no second preview read, onegetUnreadSeqsinstead of 1,000getUnreadSeq. The "this branch" column measures that model. Both runs used the same machine, back to back, with load average between 9 and 16.Tests
FeedObservedPreviewTest: the list built from streamed previews equals the one built from a direct read, a preview change doesn't query the previews again, and every row's stamp comes from onegetUnreadSeqscall.ChatMessageDaoTest: a chat with no metadata row is left out,getUnreadSeqsagrees withgetUnreadSeqacross more keys than one statement takes, and its plan uses the primary key.getUnreadSeqs, giving each pointer a stamp equal to its id. Five of them stubbedgetUnreadSeqthat way already;FeedDeletedMessageTesthad relied on the relaxed mock's default.