Skip to content

Fix large conversation load - #321

Open
RankoR wants to merge 8 commits into
GrapheneOS:mainfrom
RankoR-GOS:fix-large-conversation-load
Open

RankoR wants to merge 8 commits into
GrapheneOS:mainfrom
RankoR-GOS:fix-large-conversation-load

Conversation

@RankoR

@RankoR RankoR commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

Fixes #304

The screen loaded the whole conversation in one query and held every message in memory. The query groups on messages._id and orders by received_timestamp, so SQLite sorted the entire thread into temp b-trees before it could return a single row - 35 s and ~98 MB of Java heap for an 80000-message conversation, with an empty screen the whole time.

Fix:

  • LIMIT in a subquery over messages, before the joins and the GROUP BY. A LIMIT on the outer statement doesn't help - the sort still runs over the whole conversation first. Bounding the subquery bounds both temp b-trees to the window.
  • A (conversation_id, received_timestamp) index, schema v5. index_messages_sort can't serve this query: status sits between those two columns and is filtered with a non-indexable <>.
  • One window that grows, not pages. Open on the newest 500, double it when the user scrolls within 100 items of the oldest loaded message. It stays one query, one cursor, one observer URI, so invalidation, scroll position and "nothing older left" (a short row count) stay trivial. Paging would have meant replacing that pipeline - the widget, the selection delegate and the photo viewer all read the same URI - for the same user-visible result.

Benchmarks:

Conversation Open -> messages on screen SQLite query Rows loaded Java heap
80,000 messages 35,453 ms -> 100 ms 35,153 ms -> 32 ms 80,000 -> 500 97.6 MB -> 27.5 MB
300 messages 35 ms -> 57 ms 13 ms -> 29 ms 300 26.3 MB -> 26.2 MB
40 messages 9 ms -> 20 ms 3 ms -> 7 ms 40 26.2 MB -> 26.2 MB

Scrolling back through the 80,000-message thread, window doubling each time:

Window 500 1,000 2,000 4,000
Query 30 ms 60 ms 70 ms 250 ms
Query -> list updated 18 ms 47 ms 39 ms 73 ms

Java heap after flinging back to 4,000 loaded messages: 76 MB - still below what the old code needed just to open the thread.

One-time v4 -> v5 upgrade on that database: 36 ms. The index costs 1.4 MB for 80,000 messages.

@RankoR
RankoR marked this pull request as ready for review September 17, 2026 21:07
@RankoR
RankoR requested review from inthewaves, m4pl and sdsantos and removed request for inthewaves and m4pl September 17, 2026 21:07
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.

v13: App stuck loading messages indefinitely on owner profile in long conversations (~80k messages)

1 participant