What causes the choppy and inconsistent performance of requestAnimationFrame on Ubuntu's Chrome browser?

I'm at a loss here, unsure of what might be causing this issue.

After developing a game engine with webgl, I conducted testing primarily on Firefox where everything ran smoothly without any lag or stuttering, even during more intensive tasks like blending with multiple framebuffers.

However, when I switched over to Chrome, the story changed completely. Chrome struggled to maintain a stable fps, even when running simple tasks. To troubleshoot, I ran an experiment to determine if the issue lied within my code or the requestAnimation loop. Here's the code snippet I used:

<!DOCTYPE html>
<html>
<body>
<div id="fpsCounter"></div>

Lowest fps
<div id="minFps"></div>

<br>
Highest fps
<div id="maxFps"></div>
<script>
    // Code Snippet
</script>
</body>

</html>

The code snippet continuously loops the animation frame and displays the fps in a div element. In Firefox, the code performed well, averaging around 58 fps without dropping below 52. However, Chrome struggled to reach 40 fps and frequently dipped below 28. Interestingly, Chrome exhibited occasional bursts of high speeds, reaching a peak of 99 fps, but consistent performance at 60 fps is more crucial.

Additional Details:

Firefox version: 55.0.2 64-bit
Chrome version: 60.0.3112.78 (official version) 64-bit
OS: Ubuntu 16.04 LTS
Ram: 8gb
GPU: gtx 960m
Cpu: intel core i7HQ

Here's a snapshot of Chrome's performance: https://i.sstatic.net/zD70S.png

Answer №1

For the purpose of testing, I created a simple HTML page:

<!DOCTYPE html>
<html>
<head>
    <title>requestAnimationFrame</title>
</head>
<body>
    <canvas id="canvas" width="300" height="300"></canvas>
    <script>
    "use strict"

    // (tested in Ubuntu 18.04 and Chrome 79.0)
    //
    // requestAnimationFrame is not precise
    // often SKIPs a frame
    //

    function loop() {
        requestAnimationFrame(loop)
        var ctx = document.getElementById("canvas").getContext("2d")
        ctx.fillStyle = "red"
        ctx.fillRect(100,100,200,100)
    }

    loop()
    </script>
</body>
</html>

Check out this summary in the dev tools image

No issues with memory leaks were identified, and the scripting execution time was found to be insignificant.

View the FPS in the dev tools image

The FPS exhibited inconsistent behavior, particularly while running Chrome on Ubuntu.

The root cause in this particular test was linked to hardware acceleration.

The FPS performance improved when hardware acceleration was disabled.


UPDATE

Further tests were conducted using a page with a single canvas element. Based on these tests, it can be concluded that browsers are complex and may not always run smoothly.


Proposed Architecture for Games

var previousTimeStamp = 0

function mainLoop(timeStamp) {
    if (! shallSkipLoop(timeStamp)) { gameLoop() } 
    requestAnimationFrame(mainLoop)
}

function gameLoop() {    
    // Implement game logic here
}    

function shallSkipLoop(timeStamp) { 
    var deltaTime = timeStamp - previousTimeStamp
    previousTimeStamp = timeStamp
    //
    // Preventing skipping frames under 1000 / 60 ms!!!
    // This issue arises when the browser delays executing a frame 
    // in an attempt to sync with the next screen refresh;
    // however, it may lead to unsynchronized frames: 
    // one very short (e.g., 5ms) and the other significantly longer (e.g., 120ms)
    // This behavior could potentially be a browser bug
    //
    return deltaTime < 16
}

requestAnimationFrame(mainLoop)

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Creating a div resizing function using only JavaScript is a fun and useful project to tackle

Seeking help to create a div resizer using only pure JavaScript as jQuery is restricted. The current functionality works, but breaks when the position of the slider-div is not set to absolute. Any solutions to fix this issue would be greatly appreciated. ...

Perform a series of database queries one after the other, ensuring they are completed before

Although the database queries themselves are working fine, I am facing an issue with executing them sequentially in Node. Here is an example of the queries I need to execute in order: DELETE FROM myTable; INSERT INTO myTable(c1, c2, c3) VALUES (x, y, z); ...

Protractor will pause for 30 seconds once the page has finished loading in Angular 2

I'm currently working on creating my first end-to-end tests for an Angular 2/4 application using Protractor. So far, everything is running smoothly as the pages load and input fields are successfully filled. However, I've encountered a major iss ...

Unique: "Unique One-Step Deviation in Date Comparison"

A Little Background Information: I am working with data points that span from the current day to 5 days ahead, in 3-hour intervals (such as 10pm, 1am, 4am, 7am...). My goal is to organize these data points into arrays sorted by date, with each array repre ...

AngularJS is encountering an issue where it cannot locate the App Module

Whenever I attempt to execute this code, I encounter errors. Below is the code followed by the error message: index.html: <!DOCTYPE html> <html> <head> <meta id="meta" name="viewport" content="width=device-width, initial-scale=1 ...

Quicker method for displaying an element in an array than utilizing a for loop

Having an array as shown below: var arra= new String [50,50]; // New entries are added to the array and for each row added, count is increased by 1. The columns go up till incount which is always less than 50. for(i=0;i<=count;i++) { for(j=0;j<in ...

Babel is failing to transpile the Modal component from material-ui-next to ES5

Issue with Babel transpiling Modal component from material-ui-next Here is my .babelrc configuration: { "presets": ["es2015", "react", "stage-1", "stage-2", "stage-3"] } This is the webpack-config.js setup: var webpack = require('webpack'); ...

Tips for transitioning this JavaScript code into jQuery syntax

Below is my JavaScript code: javascript: function executeCode() { var d = document; try { if (!d.body) throw (0); window.location = 'http://www.example.com/code?u=' + encodeURIComponent(d.location.href); } catch (e) { ...

Linux web server blocking requests across different domains, even with correct Access-Control-Allow-Origin headers set

I am facing an issue with my Ubuntu web server running a React app. There are two files on the server that handle requests made by the website, but for some reason, clients are unable to make requests to the server. Server.js: const express = require(&apos ...

Here is a way to attach a function to dynamically generated HTML that is returned in an AJAX request

As I was working on a new function development project, I encountered a situation where I had to add a function to dynamically generated HTML through an ajax call. The following is a snippet of the code: $.ajax( 'success': function(data){ ...

Enhance the standard input control in Vue.js by extending it to include features such as

Incorporating vue.js: Can you enhance a standard HTML input without the need for a wrapper element? I am interested in customizing a textarea like so: Vue.component('custom-textarea', { data () => { return { } }, template: &apo ...

Displaying a dynamic menu using Angular's ngFor loop

I am attempting to create a menu with sub-menus. The desired structure for my menu is outlined below. However, the demo I'm testing is not producing the correct structure. Check out the demo here. "Sub Test": { // Main menu "Example1":"hai",//sub ...

Preventing event duplication through clone() method

I've successfully duplicated my HTML elements using this JavaScript code, but I'm having trouble copying the events associated with the code. Can anyone provide a solution? <script type = "text/javascript" language = "javascript"> f ...

Tips for handling the rejection of a promise within a callback function in Node.js

How can we effectively incorporate a catch statement within a rejectionCallback function of a promise? Is it feasible or advisable to structure the code in this manner? Would the Promise object need to be passed into the rejection function in such a scena ...

mootools.floor dispose function malfunctioned

I am attempting to implement form validation with the following code: However, it does not seem to be working properly. <form name="niceform" id="third" action="" class="niceform" method="post" enctype="multipart/form-data"> <div class ...

Client-side rendering for NextJS server components is also supported

I am currently working with Material UI v5.11.16 in a nextjs environment using v13.3.0. I followed the official documentation setup for my nextjs project which can be found here. So far, I have successfully integrated Material UI components without having ...

The functions Show() and Hide() may not work in all scenarios within jQuery

I'm currently developing a website that allows users to participate in quizzes. Each quiz consists of 20 questions divided into three sections: 1 mark for 10 questions, 2 marks for 5 questions, and 4 marks for 5 questions. For each question, there are ...

When clearInterval is used, the value of the variable is wiped out

My goal is to constantly update the text of a <p> element every 100ms, increasing the number by one each time. This process should only be triggered when the user clicks on the screen and stop once the user releases the click. The issue I'm fac ...

Arrow icon from Material UI for a smaller device

As I work on coding a tab bar, I have encountered an issue where the indicator arrow button () is not displaying when the width of the tab bar goes below 600px. I would like it to appear like this: https://i.stack.imgur.com/PDum9.png However, currently i ...

Error: The "res.json" method is not defined in CustomerComponent

FetchData(){ this.http.get("http://localhost:3000/Customers") .subscribe(data=>this.OnSuccess(data),data=>this.OnError(data)); } OnError(data:any){ console.debug(data.json()); } OnSuccess(data:any){ this.FetchData(); } SuccessGe ...