2

Chrome/Firefox are deciding to fire requestAnimationFrame at 30FPS. The profiler shows most of the time is spent idling, so its not cpu cycles being burned up.

I tried writing a delta timing to "catch up" / stay synced. The FPS is correct according to my FPS meter, but the result is very choppy animating. I also tried Drawing immediately after each Update, still choppy.

I am running a very vanilla rAF paradigm and notice the window size affects the FPS, but the profiler doesn't seem to explain why the FPS drops at full screen

        let start = null;
        let step = (timestamp)=>{
            if(thisTimerID !== scope._timerID){
                return;
            }
            start = start || timestamp + delay;
            let current = timestamp;
            let delta = current - start;

            if(delta >= delay) {
                this.Update();
                this.Draw();
                start = timestamp;
            }
            requestAnimationFrame(step);
        };
        thisTimerID = this._timerID = requestAnimationFrame(step);

Should I try requestAnimationFrame, and if I detect a low FPS when initializing, fall back to setInterval? Should I just use requestAnimationFrame anyway? Maybe there's a flaw in my delta timing logic? I know theres a huge flaw because if you switch tabs then come back, it will try to catch up and might think it missed thousands of frames!

Thank you

EDIT: requestAnimationFrame IS firing at 60fps under minimal load. It is the Draw method that is causing the frame rate to drop. But why? I have 2 profiles showing a smaller resolution runs at 60fps, full screen does not.

60FPS 350x321 Resolution: 60fps 350x321

38FPS 1680x921 Resolution: 38fps 1680x921

What's really strange to me, is the full screen version is actually doing LESS work according to the profiler.

applejacks01
  • 249
  • 1
  • 18
  • What's the value of `delay` in your code? – Herohtar Apr 06 '18 at 20:46
  • 1000/60, so about 16.67 – applejacks01 Apr 06 '18 at 20:52
  • I think there might be a problem with `start = timestamp - missedTime;`... it seems like it will keep adding up and causing your code to think the time was way off. – Herohtar Apr 06 '18 at 21:03
  • That only happens when the timing threshold has been met. Then all the "missed frames" get fired. The timestamp is always "now" and missedTime is the amount of time still waiting for the next frame. Maybe I used a bad name for that variable? I changed it to currentTime. I dont see how its going to keep accumulating though – applejacks01 Apr 06 '18 at 21:12
  • I think I'm going to try a "fallback" to setinterval. My idea is to run some quick test to analyze the max FPS of requestanimationframe. If it is less than 60, use setinterval. Might work? I can use my same "frame sync" logic in the set interval and I think it will work better because the frame rate of setinterval will be much closer to desired – applejacks01 Apr 06 '18 at 22:34
  • Is there a lot of DOM rendering going on? Idle JS does not mean nothing is happening. You dont need to test delay 60fps is the max and default rate. If you do, set delay to under the needed rate as the time in not perfect. A value of 16 will fix the rate if the rendering takes less time than needed to render the frame in time before the next frame is due and there is time for the browser's rendering needs to be completed as well. Also your logic will skip rendering the first frame. It is bad practice to force rendering/update when the tab can not be seen, that is why rAF stops firing. – Blindman67 Apr 06 '18 at 23:52
  • See this link https://stackoverflow.com/a/38709924/3877726 for why rAF is better than timers. I have done many answers in regard to why rAF is better than any other timing methods. – Blindman67 Apr 06 '18 at 23:56
  • Thank you @Blindman67. I changed the code to render the first frame (I should have set start to timestamp + delay). It's late now, but tomorrow I will test on the problem machine setting delay to 16 (or less) and see if that helps. I did find out that rAF IS running at 60fps on that machine for a very simple callback. I really didnt see much going on in the profiler, of anything whatsoever. 90% of the profile time was spent idling. Maybe that doesnt mean anything for rAF? – applejacks01 Apr 07 '18 at 03:57
  • @Blindman67 please see the edits to this post. I included new statistics showing some weirdness depending on the window size – applejacks01 Apr 07 '18 at 14:37
  • What is the mean render time of a single frame? Showing times over 7s does not help. The frame render for low res could be just below 16ms, and high res just over 17ms, so work for low res is 60*16ms = 960ms and high res 30*17=560ms. First line of the rAF function `var now = performance.now()` and last line `renderTime += performance.now()-now; renderCount += 1; var meanTime = renderTime / renderCount;` create`renderTime` and `renderCount` outside the function set to 0. That will give you you mean rendering time. – Blindman67 Apr 07 '18 at 15:36
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/168462/discussion-between-applejacks01-and-blindman67). – applejacks01 Apr 07 '18 at 16:11
  • I think this stumped everyone – applejacks01 Apr 12 '18 at 01:42

0 Answers0