Open yurkobb opened 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?
@cvennevik yes that would be welcome 🙇♂️
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.
(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 In 7.4s, spent ~300ms on rendering.
Phanpy In 6.0s, spent ~1200ms on rendering.
Second test, continuing from the last test's scroll point, and lasting slightly longer:
Mastodon web UI In 10s, spent ~600ms on rendering.
Phanpy 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.
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.
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:
useScrollFn.js
, in useLayoutEffect
, by scrollableElement.scrollTop
and scrollableElement.scrollLeft
onScroll
's use of scrollableElement
only triggers "mini"-recalculations that take a fraction of a millisecond each.media.jsx
, by const maxAspectHeight = window.innerHeight // ...
timeline.jsx
, by something my stack trace can't pin down, but likely the references to .clientHeight
and .offsetWidth
useTruncated.js
, by const { scrollHeight } = ref.current
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.
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
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.
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:
blur(...)
on many elements
mix-blend-mode: luminosity
on .alt-badge
and .media-post
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.
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:
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):