android icon indicating copy to clipboard operation
android copied to clipboard

setInterval(()=>null,0) makes any animation much smoother

Open sashok1337 opened this issue 5 years ago • 10 comments

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

sashok1337 avatar Sep 28 '19 10:09 sashok1337

What about the cpu usage? I would guess that cpu usage is much higher with the setTimeout

farfromrefug avatar Sep 30 '19 18:09 farfromrefug

@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.

sashok1337 avatar Sep 30 '19 19:09 sashok1337

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 avatar Sep 30 '19 20:09 vmutafov

@vmutafov thank you so much! Will wait for any results!

sashok1337 avatar Sep 30 '19 20:09 sashok1337

@vmutafov any progress?

sashok1337 avatar Oct 07 '19 18:10 sashok1337

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.

vmutafov avatar Oct 10 '19 08:10 vmutafov

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 avatar Oct 14 '19 15:10 vmutafov

@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

sashok1337 avatar Oct 14 '19 15:10 sashok1337

@vmutafov On Android 10 and updated NativeScript 6.2.0 the same situation ezgif com-video-to-gif

sashok1337 avatar Nov 07 '19 11:11 sashok1337