android
android copied to clipboard
setInterval(()=>null,0) makes any animation much smoother
Environment
- CLI: 6.1.2
- Android Runtime: 6.0.2 / 6.1.2
Describe the bug
I'm working on custom animation (screen blinking at 60fps) on Android, and I was very surprised that using of stupid setInterval(() => {...}, 0)
works much better that the native android's Choreographer.
With setInterval(() => {...}, 0)
I've got stable 60 FPS even on android 5 devices, but with Choreographer (that should work much efficiency, code below) I got drops to 50 FPS on powerful OnePlus 6 on Android 9.0
android.view.Choreographer.getInstance().postFrameCallback(...);
But if I write down setInterval(() => null);
near the Choreographer callback definition - I will achieve stable FPS and low GPU utilisation (LOL, right?).
To Reproduce
I have created app on playground where everybody can test it. Turn on 'Profile GPU rendering' - 'On screen as bars' in 'developer options' menu and launch this simple app with simple loader on 2 pages - one with absolutely empty component, another one with setInterval(() => {}, 0)
in OnInit.
Sample project Nativescript Playground
Additional context I've recorded animations to demonstrate this behaviour Imgur And my question on StackOverflow (without any answer) link
What about the cpu usage? I would guess that cpu usage is much higher with the setTimeout
@farfromrefug most likely that you are absolutely right. But in my case (and in case of any heavy animation) low render time is much more preferred than low CPU usage. Especially in low-duration cases (mine is 5 second long, but stable 60 fps is critical).
This hack situation is very interesting, cos, as I think, It can be caused by two reason:
- when android OS sees that our app requires power - it "prioritize" it and gives us additional time slots for computing smth. It can be useful in many different situations so it should be described in officiall docs I think.
- it is kind of a bug, and after fix - thousands of apps will be boosted up, up to 50% :)
P.S.: I can't find 'Show CPU usage' in developer's options... So I can't measure it.
I would suggest to try profiling with the Android Studio Profiler. I'll look into the problem tomorrow. Thank you all for the great feedback and examples :) I have some things in mind regarding the background work in NativeScript apps as currently the JS is executed on the main thread and this in turn leads to Java Threads and Runnables being in practice executed on the main thread. I'll keep you in touch while I look into these problems :)
@vmutafov thank you so much! Will wait for any results!
@vmutafov any progress?
Hi @sashok1337 , sorry for the delay, we had some high priority issues for the 6.2.0 release and had to look into them. I'll keep you in touch when I look at your problem.
I started looking into your app, sorry for the delay. Perhaps I'm missing something, but where in the provided Playground link is the usage of the Android Choreographer?
Beware that, as far as I know, any callback you post to the Choreographer
's postFrameCallback
would be executed when redrawing a frame (every 16-17ms). This might create some jank in NativeScript apps, as calling native Java/Kotlin methods through JS/TS has some performance cost (although small, it may be seen in some animation cases).
setTimeout
however is different, it doesn't call the callback on every frame redraw, but uses the Main thread Handler to post a message and executes on the main thread when the Android looper has time.
Perhaps I am missing something about the example as the animations support in NativeScript is implemented in the core modules and I may not be understanding something correctly.
@vmutafov I'm using Android Choreographer in my app, example app works without it but with same symptoms.
My animation affects only background color. And now i'ts working inside frame callback, but in the presence of setInterval(() => null);
Ok, I will make additional example in a few minutes
@vmutafov On Android 10 and updated NativeScript 6.2.0 the same situation