82
votes

I am moving 10,000 small div elements in a css3 experiment from the top of the browser viewport to the bottom. For this test I use 2 different approaches:

  1. With GPU acceleration using translate3D(x, y, z) or translateZ(0)
  2. No GPU acceleration by simply adjusting the top property in css

Using NO hardware-acceleration runs fairly smooth on Google Chrome.

If I enable hardware-acceleration performance becomes a lot worse. It's so bad the boxes aren't even spread out evenly anymore:

With GPU/Hardware acceleration:



Without GPU/Hardware acceleration:



Question

Why is that so? Shouldn't using the GPU improve performance?

Demo application

https://www.timo-ernst.net/misc/hwtest/

Source

https://github.com/valnub/hwtest

My hardware used for test

  • Apple Macbook Pro 15" 2015 Model
  • CPU 2,8 GHz Intel Core i7
  • 16 GB RAM
  • macOS Big Sur 11.2

Update (2014-11-13): Since this question is still attracting attention I'd like to point out that the problem itself still seems to exist although the mentioned stuttering might not be visible anymore in the provided demo on modern hardware. Older devices might still see performance issues.

*Update II (2021-02-17): The problem still persists but you will have to increase the number of boxes being moved in the demo based on the hardware used. I changed the UI of the demo app so you can now adjust the number of boxes moved to create a stuttering animation for your specific hardware. To replicate the issue I recommend to create enough boxes to see stuttering with GPU/hardware acceleration enabled. Then tick off the box and run the test again without acceleration. The animation should be smoother.

6
The real question is why some browsers want authors to resort to silly hacks like "null" transforms to activate hardware acceleration. Firefox defers to the GPU as much as possible, while IE chooses to ACCELERATE _ALL_ THE THINGS! But interesting question here nevertheless, as it seems to demonstrate that hacks like this can even backfire sometimes.BoltClock♦
@BoltClock'saUnicorn Basically I agree with you. But hasn't it always been like this with cross-browser issues? :-)Timo Ernst
I asked this question quite a while ago but I noticed now that the number of items moved seems to have a big impact on the problem. Moving few big objects is more performant than moving lots of small items when using 3D-acceleration because all the 3D-accelerated layers have to be transferred to the GPU and the way back. So even if the GPU does a good job, the transfer of many objects might be a problem so that using GPU acceleration might not be worth it.Timo Ernst
I see no performance difference in the example on any browser and have voted to close as no longer reproducible.Jason C
@Timo Just checked on whatever the latest Firefox and Chrome are, and IE11, on Windows 7 64-bit, on a fairly old 2.3 GHz i5 Thinkpad with an nVidia 4200M, both options seem smooth to me. shrugJason C

6 Answers

7
votes

The reason animation was slower when you added the null transform hack (translateZ(0)) is that each null 3D transform creates a new layer. When there are too many of these layers, rendering performance suffers because the browser needs to send a lot of textures to the GPU.

The problem was noticed in 2013 on Apple's homepage, which abused the null transform hack. See http://wesleyhales.com/blog/2013/10/26/Jank-Busting-Apples-Home-Page/

The OP also correctly noticed the explanation in their comment:

Moving few big objects is more performant than moving lots of small items when using 3D-acceleration because all the 3D-accelerated layers have to be transferred to the GPU and the way back. So even if the GPU does a good job, the transfer of many objects might be a problem so that using GPU acceleration might not be worth it.

98
votes

I always add :

-webkit-backface-visibility: hidden;
-webkit-perspective: 1000;

When working with 3d transform. Even "fake" 3D transforms. Experience tells me that these two lines always improve performances, especially on iPad but also on Chrome.

I did test on your exemple and, as far as I can tell, it works.

As for the "why" part of your question... I don't know. 3D transform are a young standard, so implementation is choppy. That's why it's a prefixed property : for beta testing. Someone could fill a bug report or a question and have the team investigate.

Edit per August 19th 2013:

There's regular activity on this answer, and I just lost an hour finding that IE10 also need this. So don't forget :

backface-visibility: hidden;
perspective: 1000;
6
votes

Interesting. I've tried playing with a few options in about:flags, specifically these ones:

GPU compositing on all pages Uses GPU-accelerated compositing on all pages, not just those that include GPU-accelerated layers.

GPU Accelerated Drawing Enable GPU accelerated drawing of page contents when compositing is enabled.

GPU Accelerated Canvas 2D Enables higher performance of canvas tags with a 2D context by rendering using Graphics Processor Unit (GPU) hardware.

Enabled those, tried it and failed miserably with the tickbox enabled (just like you did). But then I noticed yet another option:

FPS counter Shows a page's actual frame rate, in frames per second, when hardware acceleration is active.

Given the highlight in the flag description, I'd speculate that hardware acceleration was, in fact, on for me even without the ticked checkbox since I saw the FPS counter with the options above turned on!

TL;DR: hardware acceleration is, in the end, a user preference; forcing it with dummy translateZ(0) will introduce redundant processing overhead giving the appearance of lower performance.

0
votes

Check chrome://flags in chrome. It says

"When threaded compositing is enabled, accelerated CSS animations run on the compositing thread. However, there may be performance gains running with accelerated CSS animations, even without the compositor thread."

0
votes

My expericence is that GPUs aren't generally faster for all kind of graphics. For very "basic" graphics they can be slower.

You might have gotten different result if you were rotating an image - that's the kind of thing GPUs are good at

Also consider that translateZ(0) is an operation in 3 dimensions, while changing top or left is a 2 dimensional operation

-2
votes

I saw you two demo, I think I know the reason you confused:

  1. The animation elements Do not use the left or top to change the location, try to use the -webkit-transform;
  2. All child elements need to turn on hardware acceleration such as use translateZ () or translate3D;
  3. FPS measure animation fluency, your demo FPS on average only 20FPS.

Above, only a personal opinion, thank you!