Skip to content

Add timeline item prefetching #4399

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Mar 20, 2025
Merged

Conversation

jmartinesp
Copy link
Member

@jmartinesp jmartinesp commented Mar 12, 2025

Content

This should trigger when getting close the start of the loaded timeline, making scrolling back smoother, specially when combined with the persistent event cache.

Motivation and context

Try to make scrolling a bit smoother.

Fixes #4391 (or at least, it should help).

Tests

Ideally with the persistent event cache enabled, open a room where you've already paginated for a while and start scrolling back.

The scrolling should be smoother than before as we start prefetching the data way sooner. There may still be some 'pauses' as loading new items is not instant.

Tested devices

  • Physical
  • Emulator
  • OS version(s): 14

Checklist

  • Changes have been tested on an Android device or Android emulator with API 24
  • UI change has been tested on both light and dark themes
  • Accessibility has been taken into account. See https://github.com/element-hq/element-x-android/blob/develop/CONTRIBUTING.md#accessibility
  • Pull request is based on the develop branch
  • Pull request title will be used in the release note, it clearly define what will change for the user
  • Pull request includes screenshots or videos if containing UI changes
  • You've made a self review of your PR

@jmartinesp jmartinesp added the PR-Feature For a new feature label Mar 12, 2025
@jmartinesp jmartinesp requested a review from a team as a code owner March 12, 2025 15:46
@jmartinesp jmartinesp requested review from ganfra and removed request for a team March 12, 2025 15:46
@jmartinesp
Copy link
Member Author

Note scrolling is still choppy in debug builds, so ideally this should be tested in nightly/release builds.

Copy link
Contributor

github-actions bot commented Mar 12, 2025

📱 Scan the QR code below to install the build (arm64 only) for this PR.
QR code
If you can't scan the QR code you can install the build via this link: https://i.diawi.com/5DmxPT

Copy link

codecov bot commented Mar 12, 2025

Codecov Report

Attention: Patch coverage is 93.75000% with 2 lines in your changes missing coverage. Please review.

Project coverage is 80.05%. Comparing base (a6b8e5c) to head (badca69).
Report is 45 commits behind head on develop.

Files with missing lines Patch % Lines
...id/features/messages/impl/timeline/TimelineView.kt 93.33% 0 Missing and 2 partials ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #4399      +/-   ##
===========================================
+ Coverage    80.04%   80.05%   +0.01%     
===========================================
  Files         2067     2067              
  Lines        55234    55265      +31     
  Branches      6768     6774       +6     
===========================================
+ Hits         44210    44243      +33     
+ Misses        8707     8705       -2     
  Partials      2317     2317              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@frebib
Copy link
Contributor

frebib commented Mar 12, 2025

I tried this and I'm not sure it made much/any difference? I even tried increasing this number here to 50 and it felt about the same again https://github.com/element-hq/element-x-android/pull/4399/files#diff-594345b3940e91c8414ebe16d73e789d073cb7f057f03b7e9dc4d0941bc97096R182
Curiously I'm also not seeing the new debug log lines in my release build- do they get "compiled out" or something in release builds?

@jmartinesp
Copy link
Member Author

jmartinesp commented Mar 12, 2025

I tried this and I'm not sure it made much/any difference? I even tried increasing this number here to 50 and it felt about the same again

Oh, that's weird, there was definitely a difference for me in a 5 y.o. device, it wasn't always smooth when scrolling back, but it was most of the time, while it was definitely a lot more janky before. Are you enabling the persistent event cache for the tests?

Also, I think it doesn't work as well as it should in encrypted rooms because the encryption layer does extra work that slows down delivering new items from the SDK to the app. I tried it in some non-encrypted rooms and I didn't see a single indicator while scrolling up, while I still saw a few in some small encrypted ones.

Curiously I'm also not seeing the new debug log lines in my release build- do they get "compiled out" or something in release builds?

You need to enable those by changing this value here to true. We're discussing removing this restriction, so it'll probably be gone soon.

@frebib
Copy link
Contributor

frebib commented Mar 12, 2025

Are you enabling the persistent event cache for the tests?

Yep. Clearing cache first too.

You need to enable those by changing this value here to true.

With this enabled, I do see it doing something, thanks for the tip 💡 I'll have a play around with it.

As I'm understanding it, it will attempt to request pagination at most one time (although in practice it's usually zero unless you scroll in just the right way) and then stop until the user scrolls again. What I would probably expect as a user (and what I'm pretty sure most of the other "mainstream" chat apps do is paginate repeatedly until a desired number of messages are ready but off-screen. Is that a desirable behaviour here? I understand that it's a tradeoff between responsiveness and conservative resource use.

@ganfra
Copy link
Member

ganfra commented Mar 12, 2025

As I'm understanding it, it will attempt to request pagination at most one time (although in practice it's usually zero unless you scroll in just the right way) and then stop until the user scrolls again. What I would probably expect as a user (and what I'm pretty sure most of the other "mainstream" chat apps do is paginate repeatedly until a desired number of messages are ready but off-screen. Is that a desirable behaviour here? I understand that it's a tradeoff between responsiveness and conservative resource use.

Yes, but we'll get more improvements later from the rust sdk with probably some automatic pagination!

@frebib
Copy link
Contributor

frebib commented Mar 12, 2025

Out of my own curiosity, I had a poke at trying to make this do what I would like, and came up with this adaptation of Jorge's change from this PR frebib@6e3b479
I'm far from a UX expert/app developer, but I'm gonna roll with this for a while. At least with this patch on my phone with my homeserver, it's very hard/nearly impossible to hit the loading spinner unless in an encrypted room (where pagination seems a lot slower for some reason?). When you open the room, the app does this, then stops:

03-12 20:42:27.180  6436  6436 D org.matrix.rust.sdk: elementx: Prefetching pagination with 0 off-screen (0 total) items |
03-12 20:42:27.312  6436  6436 D org.matrix.rust.sdk: elementx: Prefetching pagination with 21 off-screen (15 total) items |
03-12 20:42:29.342  6436  6436 D org.matrix.rust.sdk: elementx: Prefetching pagination with 59 off-screen (53 total) items |
03-12 20:42:31.803  6436  6436 D org.matrix.rust.sdk: elementx: Prefetching pagination with 91 off-screen (85 total) items |
03-12 20:42:33.823  6436  6436 D org.matrix.rust.sdk: elementx: Prefetching pagination with 124 off-screen (118 total) items |
03-12 20:42:35.450  6436  6436 D org.matrix.rust.sdk: elementx: Prefetching pagination with 152 off-screen (146 total) items |
03-12 20:42:37.770  6436  6436 D org.matrix.rust.sdk: elementx: Prefetching pagination with 186 off-screen (180 total) items |

@jmartinesp
Copy link
Member Author

200 items seems like way too much IMO 😅 . I guess we should play around a bit with that value. Also, removing the 'is scrolling' check seems to help, noted.

I don't really understand what the offscreenEvents represents in your code though.

@ganfra
Copy link
Member

ganfra commented Mar 17, 2025

@jmartinesp what are we doing with this then? Trying to improve or merge as is?

@jmartinesp
Copy link
Member Author

I think we may want to tweak it a bit more before merging it. I'll try to get some time today to look at this again.

This should trigger when getting close the start of the loaded timeline, making scrolling back smoother, specially when combined with the persistent event cache.
@jmartinesp
Copy link
Member Author

I think I found a sweet spot prefetching at -40 items and using snapshotFlow so we don't have to wait for a recomposition to trigger the 'load more' action. I'll experiment with this a bit more, but I just loaded the whole previously loaded history of an encrypted room (~1000 items) at full speed without a single loading indicator.

…t, as well as an extended threshold (-40 items)
@jmartinesp jmartinesp force-pushed the feat/add-timeline-prefetching-mechanism branch from 847cf07 to 8f129eb Compare March 17, 2025 15:31
prefetch: () -> Unit,
) {
// We're using snapshot flows for these because using `LaunchedEffect` with `derivedState` doesn't seem to be responsive enough
val firstVisibleItemIndexFlow = snapshotFlow {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks wrong, I don't think snapshotFlow should be created in the Composable scope, but are intended to be created in the CoroutineScope they are used. I think here you are recreating flows each time

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, it should be used inside the LaunchedEffect. Now I'm worried that this was actually working and the tests passed 😓 .

Copy link

@jmartinesp jmartinesp requested a review from ganfra March 19, 2025 11:24
Copy link
Member

@ganfra ganfra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets merge and see how it goes!

@ganfra ganfra merged commit 811ba95 into develop Mar 20, 2025
31 checks passed
@ganfra ganfra deleted the feat/add-timeline-prefetching-mechanism branch March 20, 2025 10:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
PR-Feature For a new feature
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Timeline (pagination) performance is noticeably slower than on Element X iOS
3 participants