-
Notifications
You must be signed in to change notification settings - Fork 979
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
Improve Settings screen opening performance #19940
Conversation
Jenkins BuildsClick to see older builds (1)
|
a547ec8
to
a657485
Compare
(defn delay-render | ||
[content] | ||
(let [[render? set-render] (use-state false)] | ||
(use-mount | ||
(fn [] | ||
(js/setTimeout #(set-render true) 0))) | ||
(when render? | ||
content))) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @ilmotta, I have seen the discussion on discord about this. I checked out the builds in this PR and compared to develop
on iOS and Android devices. In my experience both of develop and your PR are very and equally smooth. But I see in the videos you posted it performs better on your Android device (but seems not as smooth as on my device). I can make a small suggestion here, have you tried using reagent/next-tick
instead of js/setTimeout 0
it can perform slightly better as it places the function on a micro-task queue rather than a macro-task queue like setTimeout
(defn delay-render
[content]
(let [[render? set-render] (use-state false)]
(use-mount
(fn []
(reagent/next-tick #(set-render true))))
(when render?
content)))
Here is an Android build that uses that
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @OmarBasem, thanks a lot for reviewing the build and code. I expected iOS would perform nearly the same because things are much smoother over there. Now that you confirmed this, I guess we can say this PR is really targeting Android.
I remember when delay-render
was first implemented there was a comment about using next-tick
(maybe @ulisesmac said that), but I don't remember why we ended up using setTimeout
(maybe because it's well known among devs and the performance was the same at the end of the day).
I'll check out with next-tick
and see what comes out of it! Thanks
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@OmarBasem, I tried with next-tick
. It works the same on average. Here's how I compared them, which I think is not super scientific, but quite practical from the user's perspective.
- I enabled show taps and recorded the current and new implementation opening and closing the Settings screen many times.
- After the first video frame shows the white circle (press) I count the number for frames in the video until the Settings screen is rendered and animated at the top. There's a tiny margin for error counting like this, but should be precise enough.
The results (ignore absolute frame numbers, just how close they all are):
next-tick: 12 frames, 11 frames, 9 frames
setTimeout: 10 frames, 8 frames, 13 frames, 10 frames
So, I would say they perform essentially the same for this particular component, but I agree next-tick
can theoretically be better, even if no practical advantage could be measured for the Settings screen. Even if the number of frames to render is the same, maybe next-tick
could consume less resources? But anyway, I'll use next-tick because it's cleaner and gives the same effect.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think next-tick
could communicate the intent more clearly, because it seems we're trying to defer the rendering to relieve the cpu during some animations (?).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But anyway, I'll use next-tick because it's cleaner and gives the same effect.
I think next-tick could communicate the intent more clearly
@ilmotta @seanstrom I agree, when I find both of next-tick
and setTimeout 0
having the same effect practically I use next-tick
as I think it communicates the intent better
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we make this solution android specific so? i.e split it by platform? 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@J-Son89 the solution introduced in Icaro's PR is to use a hook instead of hiccup for delay-render
As for next-tick
, as discussed above the performance in this scenario is the same but we settled for it over setTimeout 0
because it is a little cleaner. It is not platform specific.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool cool, it's just that in your initial comment you said this was not as smooth for you on iOS.
Anyway I guess it fixes the bigger issue which is a bad android performance so that's great 🚀
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lgtm either way! 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Performance seems consistently smooth for me on my side ✅
I wonder if there's a place for us to collect some of these performance findings? Because it seems we're beginning to practically see some benefits for avoiding hiccup (in some places) and using hooks instead of reagent atoms.
Perhaps this will help shape the future of improvements around using or not using hiccup and reagent atoms.
@seanstrom, I think we don't have such a central place to look for performance findings. Maybe we have something in Notion. The closest we have in this repo I think is in |
@ilmotta thanks for sharing the above analysis. An interesting comparison indeed. I can add one more thing, have you tried using |
I haven't tried to optimize the Settings screen in any other way @OmarBasem, this is my first time touching it. Yesterday I simply rewrote the Since I'm at this PR, I tried your suggestion with But you gave me an idea (not that I'm going to implement) but since the vertical space varies wildly sometimes between devices, in the future, we could consider making Thanks again for the tips and insights 💯 |
Thank you for the explanation. The settings items showing up before animation completes creates a massive impact. It also clears two misconceptions in my head:
|
a657485
to
e9b88ec
Compare
Summary
In this PR we're rewriting
utils.re-frame/delay-render
to use hooks. The new implementation renders significantly better than what we have today, at least on Android.Current (
develop
) on a Samsung Galaxy A71, release build, Android 13current.mp4
New (PR) on a Samsung Galaxy A71, release build, Android 13
new.mp4
Areas that may be impacted
None.
Why not hiccup instead of a function call to
delay-render
?The Settings screen is rendered slightly faster if I use
delay-render
as a function call instead of hiccup. My only guess is that this is just less work to be done by Reagent, since the wrapper function is not creating a wrapper component with its own lifecycle.Naming
I would keep the name
delay-render
, as a verb (like any ordinary function), because it tells the developer that it shouldn't be treated as a component (which is named as a noun most of the time).Steps to test
As a reviewer, I kindly ask you to check this PR's build and compare with the experience from the
develop
branch of opening the Settings screen a few times. Is it better? Could you share a screen recording on Android/iOS?status: ready