marko icon indicating copy to clipboard operation
marko copied to clipboard

CPU load on https://markojs.com

Open jkleiser opened this issue 4 years ago • 4 comments

When I go to https://markojs.com in Safari (14.1.2), the CPU load on my MacBook Air goes up above 100%. If I use the Brave browser, the CPU load is closer to 25%. Still too much.

jkleiser avatar Nov 30 '21 09:11 jkleiser

Hm, this sounds eerily familiar to #1715. Do your performance devtools show if it’s running a lot of style recalculation?

tigt avatar Dec 01 '21 00:12 tigt

I haven't yet been able to detect anything like "style recalculation". However, when I viewed markojs.com in Safari with devtools open, it climbed from ca. 90% up to 100% CPU. As soon as I closed the devtools (indicated by the vertical arrow in the included screen dump from Activity Monitor), however, the CPU load started climbing to over 120%.

Markojs-Safari

jkleiser avatar Dec 02 '21 20:12 jkleiser

Yep, can confirm:

Safari devtools in Timeline tab shows 347.2% maximum CPU usage and many repeated “Layout & Rendering” tasks.

I uploaded the trace here for the Marko maintainers: markojs.com-recording.json.gz

tigt avatar Dec 02 '21 21:12 tigt

Still an issue in Safari 15.5. Its DevTools report:

Main thread

JavaScript: 0.0% (0) Layout: 1.3% (9) Paint: 98.7% (697) Styles: 0.0% (0)

Energy Impact

Very High Average CPU: 204.1%

After investigating, it looks like these are the culprits. When I turned off all of them in the Safari DevTools, the Average CPU dropped to 3.8%.

Code Elimination animation

  @keyframes pulse-red {
    0% {
      box-shadow: 0 0 0 0 rgba(255, 50, 82, 0.9);
    }

    100% {
      box-shadow: 0 0 0px 90px rgba(255, 50, 82, 0);
    }
  }

box-shadow is a notorious career performance criminal, especially when animated or transitioned. Animating transform and opacity on some pseudo-elements would probably be a good replacement.

Image placeholder popping in

.demo-page-lowres {
    filter: blur(1em) grayscale(0.6);
    opacity: 0.3;
  }

Maybe we should have two .demo-page-image elements, and toggle their opacity on and off instead, so Safari only needs to rasterize the filter once.

Demo progress bar

<div.demo-page-progress style={ transform: `scaleX(${Math.min(1, input.progress * (input.buffered ? 1 : 1/0.9))})` }/>

The worst part is this progress bar doesn’t even display right now — it’s missing either right: 0 or width: 100%. (I checked — not my fault in https://github.com/marko-js/website/pull/63!)

It looks like doing the scaleX() dynamically in JS is flummoxing Safari. Slapping will-change: transform on .demo-page-progress made it much happier.

tigt avatar Jun 23 '22 19:06 tigt