skip to Main Content

I’m developing a simple music player. One thing I’ve noticed is that the GPU usage is unreasonably high despite the actual layout being pretty simple. After disabling various elements of the page, I’ve realized that the progress bar transition is what’s causing this massive GPU usage.

GPU usage

It’s weird because it seems so simple. Even if I do it in a Codepen, it’s causing this massive GPU usage:

https://jsfiddle.net/bhn9sfux/

let progressBar = document.getElementById("progressbar");
setTimeout(() => progressBar.style.width = "100%", 1000);
#progressbar {
  background: black;
  height: 10px;
  width: 0;
  transition: width 60s linear;
}
<div id="progressbar"></div>

My PC is reasonably beefy (RX Vega 56) and it can obviously still display it smoothly. That’s not the problem. What’s confusing me is how such a simple transition can even cause such a big performance consumption in the first place. I was expecting low 0-point numbers, and definitely no power consumption of "Middle" level.

Is my CSS terrible? Is there something I am overlooking about the render engine? Or is it simply how it is?

2

Answers


  1. You can try will-change property of CSS if you are trying to reduce the GPU usage or else Use requestAnimationFrame This method can help synchronize rendering with the browser’s internal animation loop, which can improve performance and reduce GPU usage.
    What i have seen is its not about your code or progress bar its about SetTimeout().

    Login or Signup to reply.
  2. The reason it’s eating up so much GPU is because you’re animating the width property. When you change a value that effects the box dimensions, (And a handful of other properties) the DOM needs to re run a bunch of calculations, which causes a full Reflow of the DOM. Which is quite expensive.

    Reflow

    By definition, “Reflow” is the process the web browser uses to
    re-calculate the positions and geometries of elements in the document.
    It’s basically the effort the browser needs to do to position every
    element in the screen every time something changes (either by a
    refresh, a screen resize or a common show/hide content action).

    Try the animation using something like clip-path, or wrapping the progress bar in a parent container with overflow: hidden; and then move the progress bar with transform: translate3d(); This way the box doesn’t change size, only position.

    Here is a simple example using clip-path:

    .bar {
      background: red;
      height: 50px;
      width: 500px;
      animation: 1s infinite alternate slidein;
      clip-path: inset(0 100% 0 0);
    }
    
    @keyframes slidein {
      from {
        clip-path: inset(0 100% 0 0);
      }
      to {
        clip-path: inset(0 0 0 0);
      }
    }
    <div class="bar"></div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search