cheeaun / phanpy

A minimalistic opinionated Mastodon web client
https://phanpy.social
MIT License
1.05k stars 102 forks source link

Sluggish scrolling on a non-high-end (mobile) device #377

Open yurkobb opened 9 months ago

yurkobb commented 9 months ago

Describe the bug

Scrolling any of the timelines as well as the settings screen has a noticeable lag on a less powerful device (see below); I suspect some CSS filters (blur?) might be at fault, but not sure how to confirm this. If this is so, maybe a toggle somewhere in settings for disabling expensive eye-candy would help?

To Reproduce Steps to reproduce the behavior:

  1. Go to the home timeline or settings (as an example)
  2. Try scrolling the page;
  3. Notice annoying lag.

Expected behavior The page should scroll / operate without any heavy-lifting on the CPU or GPU or power drain.

Screenshots

https://github.com/cheeaun/phanpy/assets/479389/eaaf04dd-bb7c-4fcc-b0bd-0b4c0f510877

Smartphone (please complete the following information):

cvennevik commented 9 months ago

I'm experiencing the same sluggishness when scrolling, and also when typing.

Device: Motorola G6 Plus OS: Android 9 (I know, my phone has not been offered any updates since 2020) Browser: Firefox for Android, version 121

I'm away from my computer for another three days, but I'd be interested in profiling the app and trying to pinpoint which parts are heaviest on the browser, and maybe compare it to the default Mastodon web app as a baseline since my phone handles that fine.

Since it's your side project, I want to check - would that be welcome, @cheeaun?

cheeaun commented 9 months ago

@cvennevik yes that would be welcome 🙇‍♂️

MaddyUnderStars commented 9 months ago

I am also experiencing the same performance issues on all devices. When you scroll down, Phanpy only ever adds new elements to the DOM, so after a while you'll end up with hundreds of statuses that on every render are iterated over and rendered. Interactions in this state are very slow, opening statuses or the right click menu takes a second. It does remove them when you scroll back up though, which fixes the perf issues. This could be (one of?) the cause of performance issues. Note of course that I'm not a react/web dev and may have no idea what I'm talking about.

cvennevik commented 9 months ago

(Edit: Turns out high-end desktop performance and mid-range mobile performance behave significantly differently, and these findings are not very relevant to mobile performance, see my later comment: https://github.com/cheeaun/phanpy/issues/377#issuecomment-1873448633)

Okay, I did some very rough and unrigorous performance measurements in Chrome DevTools, quickly scrolling down a similar number of posts.

First test, with some of the page already loaded:

Mastodon web UI image In 7.4s, spent ~300ms on rendering.

Phanpy image In 6.0s, spent ~1200ms on rendering.

Second test, continuing from the last test's scroll point, and lasting slightly longer:

Mastodon web UI image In 10s, spent ~600ms on rendering.

Phanpy image In 10s, spent ~3800ms on rendering.

So - roughly 5x difference in time spent on Rendering.

There is also a big difference in DOM size - counted by document.getElementsByTagName('*').length after the second test:

Mastodon does a trick here to reduce DOM size by, from what I can tell, saving a post's height and removing its content when it scrolls out of view, then re-adding the content when it scrolls back into view. This drastically reduces DOM size, so it may be worth copying in Phanpy, though it looks somewhat complicated. image

I would have liked to also examine memory usage, but apparently I can wrangle neither the Chrome nor Firefox devtools to measure that for me today.

What might be most interesting is if we dive into the call tree and see how much time was spent on Recalculate Style:

And if we look at the flame graph, it is peppered with dozens of ~100ms long instances of Recalculate Style, with warnings about forced reflow. image

It looks to me like there's a combination of two things here:

Here are the bits of code I've found that trigger expensive forced reflows - they may not be the "root causes", but they're what show up repeatedly in the flame graph:


If the rendering / style recalculation can be made cheaper (probably by reducing DOM size), Phanpy is going to run a lot better on lower-end devices. I don't know of an effective way to go about that except also implementing a "simplify what's out of view" strategy, but maybe there are some other, hopefully simpler ways to squeeze out better performance.

If there is a way to remove most of the forced reflow triggers, that could also go a long way to improving the experience.

Alex0007 commented 9 months ago

I guess it is somehow relates to spoiler styling.

For example lags are happening when this post is in FOV: https://dev.phanpy.social/#/mastodon.social/s/111676253056047476

cvennevik commented 9 months ago

Yeah, I feel like there's something my profiling is missing, since that post alone gives my phone framerate issues, and I can't explain that based on what I saw in my previous comment.

It looks like I may be able to remotely debug and profile Firefox on my phone, so I'll give that a try tomorrow.

cvennevik commented 9 months ago

Welp - it turns out, if you want to find performance issues on a mobile device, you should profile on said mobile device. Who'd've guessed?

When profiling Firefox on my phone, the renderer chugs at 70-90% but the trace shows no signs of style recalculation being a major factor. It looks like @yurkobb was on the money about guessing that it's some CSS effect causing the issue. Two in particular:

When I remove all instances of these, scrolling is significantly smoother. Not entirely, consistently smooth, but it immediately makes Phanpy more usable on my phone.

@cheeaun This should be more actionable than my previous find 🙇 It looks like mix-blend-mode: luminosity; is subtle enough that it could be just removed, but removing the blur effects is a bigger change which would require re-doing the CSS to look right. You're probably best suited to decide what to do about it.