Skip to content

Instantly share code, notes, and snippets.

@axemclion
Last active August 29, 2015 14:03
Show Gist options
  • Save axemclion/853d34ebd776047836f3 to your computer and use it in GitHub Desktop.
Save axemclion/853d34ebd776047836f3 to your computer and use it in GitHub Desktop.
GPU Composited CSS - Performance

Ariya Hidayat has written an excellent article on GPU Composited CSS and how it can be used to optimize web rendering performance.

The impact of adding CSS transforms is evident in developer timline and this experiment is a way to capture that information using browser-perf. The results from this experiment clearly indicate how certain CSS properties move rendering load to the GPU, and how that that impact the overall responsiveness of the page.

Pre-requisites

  1. Ensure that you have node and npm installed
  2. Ensure that you have Selenium running, or can connect to Sauce Labs
  3. Dowload this gist using git clone https://gist.github.com/853d34ebd776047836f3.git
  4. Install other dependencies using npm install

Experiment 1 - Impact of number of rectangles on the screen - Page

Run node index.js to get the data for the number for the specified number of rectangles. Remember to change the string 'addOne()' to values like addTen() or addHundred() for getting more rectangles on the screen, and seeing what the numbers for each look like.

Experiment 2 - Improvement when color is not changed - Change color vs Opacity Trick

The purpose of this experiment was to prove that the changing the color causes a paint. An effective way to achieve the same effect is to have 2 rectangles with alternative opacity.

Experiment 1

As expected, the number of composite layers, and the number of Layers change. All other things like amount of Javascript executed, paint time, etc seem to remain similar across the three cases

Metric One Ten Hundred Units Source
CompositeLayers 20.00048828 58.99951172 171.0007324 ms ChromeTimelineMetrics
CompositeLayers_avg 0.222227648 0.522119573 1.257358327 ms ChromeTimelineMetrics
CompositeLayers_count 90 113 136 count ChromeTimelineMetrics
Layers 7 17 106 count RuntimePerfMetrics
Paint 0 2.7265625 277.9980469 ms ChromeTimelineMetrics
Paint_avg 0 0.136328125 0.037915718 ms ChromeTimelineMetrics
Paint_count 1 20 7332 count ChromeTimelineMetrics

Experiment 2

In experiment 2, the higher number of Paint Counts and Composite Layers indicate the extra work that the GPU has to perform.

</tr>
Metric Color Change Opacity Change Unit
CompositeLayers 33.99902344 10.00048828 ms
Paint_count 51 5 count
Layers 6 2 count
// Experiment 2 - Changing color using opacity
var colorChange = 'http://codepen.io/ariya/full/xuwgy';
var opacityChange = 'http://codepen.io/ariya/full/ofDIh';
require('browser-perf')(opacityChange, function(err, data) {
if (err) {
console.log(err);
} else {
console.log('Results');
for (var key in data[0]) {
var val = data[0][key];
console.log([key, val.value, val.unit, val.source].join());
}
}
}, {
browsers: 'chrome',
actions: function(browser) {
return browser.sleep(500);
},
log: console.log,
debug: true
});

Here is the full data -

Experiment 1

fetchStart 0 0 0 ms NavTimingMetrics
domainLookupStart 4 3 7 ms NavTimingMetrics
domainLookupEnd 16 28 5 ms NavTimingMetrics
connectStart 0 0 0 ms NavTimingMetrics
connectEnd 2 2 5 ms NavTimingMetrics
requestStart 1 0 0 ms NavTimingMetrics
responseStart 87 80 57 ms NavTimingMetrics
domLoading 4 3 8 ms NavTimingMetrics
domInteractive 100 91 53 ms NavTimingMetrics
domContentLoadedEventStart 0 0 0 ms NavTimingMetrics
domContentLoadedEventEnd 0 0 0 ms NavTimingMetrics
domComplete 0 1 0 ms NavTimingMetrics
loadEventStart 0 0 0 ms NavTimingMetrics
loadEventEnd 0 0 0 ms NavTimingMetrics
Program 544.0014648 651.0019531 1249.999268 ms ChromeTimelineMetrics
Program_avg 0.782735921 0.841087795 1.390433001 ms ChromeTimelineMetrics
Program_max 165 169.9997559 155.0002441 ms ChromeTimelineMetrics
Program_count 695 774 899 count ChromeTimelineMetrics
FireAnimationFrame 6 3.999511719 6.000488281 ms ChromeTimelineMetrics
FireAnimationFrame_avg 0.0625 0.037378614 0.045458245 ms ChromeTimelineMetrics
FireAnimationFrame_max 1 1.000244141 1.000244141 ms ChromeTimelineMetrics
FireAnimationFrame_count 96 107 132 count ChromeTimelineMetrics
FunctionCall 162.0012207 178.9978027 177.9992676 ms ChromeTimelineMetrics
FunctionCall_avg 0.861708621 0.852370489 0.757443692 ms ChromeTimelineMetrics
FunctionCall_max 26 29 24 ms ChromeTimelineMetrics
FunctionCall_count 188 210 235 count ChromeTimelineMetrics
CompositeLayers 20.00048828 58.99951172 171.0007324 ms ChromeTimelineMetrics
CompositeLayers_avg 0.222227648 0.522119573 1.257358327 ms ChromeTimelineMetrics
CompositeLayers_max 3 6 14.99975586 ms ChromeTimelineMetrics
CompositeLayers_count 90 113 136 count ChromeTimelineMetrics
TimerFire 24 45.99951172 44.00048828 ms ChromeTimelineMetrics
TimerFire_avg 0.705882353 0.919990234 0.897969149 ms ChromeTimelineMetrics
TimerFire_max 11 29 25 ms ChromeTimelineMetrics
TimerFire_count 34 50 49 count ChromeTimelineMetrics
RecalculateStyles 46.99975586 36.00048828 235.9975586 ms ChromeTimelineMetrics
RecalculateStyles_avg 0.479589346 0.349519304 1.815365835 ms ChromeTimelineMetrics
RecalculateStyles_max 8 4.000244141 5.000244141 ms ChromeTimelineMetrics
RecalculateStyles_count 98 103 130 count ChromeTimelineMetrics
Layout 32.00024414 29.99951172 23.99926758 ms ChromeTimelineMetrics
Layout_avg 0.820519081 0.599990234 0.499984741 ms ChromeTimelineMetrics
Layout_max 26 15 11 ms ChromeTimelineMetrics
Layout_count 39 50 48 count ChromeTimelineMetrics
GCEvent 36 18.00024414 16.00024414 ms ChromeTimelineMetrics
GCEvent_avg 5.142857143 2.571463449 2.666707357 ms ChromeTimelineMetrics
GCEvent_max 27 7.000244141 7 ms ChromeTimelineMetrics
GCEvent_count 7 7 6 count ChromeTimelineMetrics
ParseHTML 1.449951172 21.00024414 19.99951172 ms ChromeTimelineMetrics
ParseHTML_avg 0.161105686 1.909113104 1.818137429 ms ChromeTimelineMetrics
ParseHTML_max 0.557128906 14.00024414 12 ms ChromeTimelineMetrics
ParseHTML_count 9 11 11 count ChromeTimelineMetrics
PaintSetup 60.00024414 90.00415039 4.582519531 ms ChromeTimelineMetrics
PaintSetup_avg 0.441178266 0.146110634 0.041659268 ms ChromeTimelineMetrics
PaintSetup_max 16 16 1.0859375 ms ChromeTimelineMetrics
PaintSetup_count 136 616 110 count ChromeTimelineMetrics
Paint 0 2.7265625 277.9980469 ms ChromeTimelineMetrics
Paint_avg 0 0.136328125 0.037915718 ms ChromeTimelineMetrics
Paint_max 0 0.999023438 13 ms ChromeTimelineMetrics
Paint_count 1 20 7332 count ChromeTimelineMetrics
EvaluateScript 24.00024414 146 131 ms ChromeTimelineMetrics
EvaluateScript_avg 2.181840376 146 131 ms ChromeTimelineMetrics
EvaluateScript_max 15 146 131 ms ChromeTimelineMetrics
EvaluateScript_count 11 1 1 count ChromeTimelineMetrics
EventDispatch 141 35.99951172 31.00024414 ms ChromeTimelineMetrics
EventDispatch_avg 141 5.99991862 5.166707357 ms ChromeTimelineMetrics
EventDispatch_max 141 23.99975586 20.00024414 ms ChromeTimelineMetrics
EventDispatch_count 1 6 6 count ChromeTimelineMetrics
XHRReadyStateChange 34 1.000244141 2 ms ChromeTimelineMetrics
XHRReadyStateChange_avg 5.666666667 0.111138238 0.222222222 ms ChromeTimelineMetrics
XHRReadyStateChange_max 22.00024414 1.000244141 1 ms ChromeTimelineMetrics
XHRReadyStateChange_count 6 9 9 count ChromeTimelineMetrics
DecodeImage 0 0 0 ms ChromeTimelineMetrics
DecodeImage_avg 0 0 0 ms ChromeTimelineMetrics
DecodeImage_max 0 0 0 ms ChromeTimelineMetrics
DecodeImage_count 9 1 1 count ChromeTimelineMetrics
ResizeImage 0 0 0 ms ChromeTimelineMetrics
ResizeImage_avg 0 0 0 ms ChromeTimelineMetrics
ResizeImage_max 0 0 0 ms ChromeTimelineMetrics
ResizeImage_count 2 2 2 count ChromeTimelineMetrics
mean_frame_time 8.249948905 9.044228188 8.350725165 ms ChromeTracingMetrics
jank 37.99233175 98.28513931 63.6345952 ms ChromeTracingMetrics
mostly_smooth 3.715000033 4.818699968 2.092000008 percentile ChromeTracingMetrics
Layers 7 17 106 count RuntimePerfMetrics
PaintedArea_total 4512218 10029906 72008498 sq pixels RuntimePerfMetrics
PaintedArea_avg 33178.07353 16282.31494 9821.126296 sqpixels RuntimePerfMetrics
NodePerLayout_avg 45.05882353 36.92 40.5625 count RuntimePerfMetrics
ExpensivePaints 0 0 0 count RuntimePerfMetrics
GCInsideAnimation 0 0 0 count RuntimePerfMetrics
ExpensiveEventHandlers 1 1 1 count RuntimePerfMetrics

Experiment 2

</tr>
<tr>
	<td>CompositeLayers_avg</td>
	<td>0.361691739</td>
	<td>0.113641912</td>
	<td>ms</td>

</tr>
<tr>
	<td>CompositeLayers_count</td>
	<td>94</td>
	<td>88</td>
	<td>count</td>

</tr>
<tr>
	<td>CompositeLayers_max</td>
	<td>7</td>
	<td>4.000244141</td>
	<td>ms</td>

</tr>
<tr>
	<td>EvaluateScript</td>
	<td>142.9997559</td>
	<td>129.9997559</td>
	<td>ms</td>

</tr>
<tr>
	<td>EvaluateScript_avg</td>
	<td>142.9997559</td>
	<td>129.9997559</td>
	<td>ms</td>

</tr>
<tr>
	<td>EvaluateScript_count</td>
	<td>1</td>
	<td>1</td>
	<td>count</td>

</tr>
<tr>
	<td>EvaluateScript_max</td>
	<td>142.9997559</td>
	<td>129.9997559</td>
	<td>ms</td>

</tr>
<tr>
	<td>EventDispatch</td>
	<td>30.00024414</td>
	<td>31</td>
	<td>ms</td>

</tr>
<tr>
	<td>EventDispatch_avg</td>
	<td>5.00004069</td>
	<td>5.166666667</td>
	<td>ms</td>

</tr>
<tr>
	<td>EventDispatch_count</td>
	<td>6</td>
	<td>6</td>
	<td>count</td>

</tr>
<tr>
	<td>EventDispatch_max</td>
	<td>16.99975586</td>
	<td>20</td>
	<td>ms</td>

</tr>
<tr>
	<td>FireAnimationFrame</td>
	<td>2</td>
	<td>10.00024414</td>
	<td>ms</td>

</tr>
<tr>
	<td>FireAnimationFrame_avg</td>
	<td>0.021978022</td>
	<td>0.117649931</td>
	<td>ms</td>

</tr>
<tr>
	<td>FireAnimationFrame_count</td>
	<td>91</td>
	<td>85</td>
	<td>count</td>

</tr>
<tr>
	<td>FireAnimationFrame_max</td>
	<td>1</td>
	<td>1.000244141</td>
	<td>ms</td>

</tr>
<tr>
	<td>FunctionCall</td>
	<td>134.0009766</td>
	<td>147.0024414</td>
	<td>ms</td>

</tr>
<tr>
	<td>FunctionCall_avg</td>
	<td>0.937069766</td>
	<td>1.080900304</td>
	<td>ms</td>

</tr>
<tr>
	<td>FunctionCall_count</td>
	<td>143</td>
	<td>136</td>
	<td>count</td>

</tr>
<tr>
	<td>FunctionCall_max</td>
	<td>20.99975586</td>
	<td>23</td>
	<td>ms</td>

</tr>
<tr>
	<td>GCEvent</td>
	<td>16.00048828</td>
	<td>29.99951172</td>
	<td>ms</td>

</tr>
<tr>
	<td>GCEvent_avg</td>
	<td>2.666748047</td>
	<td>5.999902344</td>
	<td>ms</td>

</tr>
<tr>
	<td>GCEvent_count</td>
	<td>6</td>
	<td>5</td>
	<td>count</td>

</tr>
<tr>
	<td>GCEvent_max</td>
	<td>8</td>
	<td>25</td>
	<td>ms</td>

</tr>
<tr>
	<td>Layout</td>
	<td>14.99951172</td>
	<td>22</td>
	<td>ms</td>

</tr>
<tr>
	<td>Layout_avg</td>
	<td>1.24995931</td>
	<td>2.2</td>
	<td>ms</td>

</tr>
<tr>
	<td>Layout_count</td>
	<td>12</td>
	<td>10</td>
	<td>count</td>

</tr>
<tr>
	<td>Layout_max</td>
	<td>7.999755859</td>
	<td>12</td>
	<td>ms</td>

</tr>
<tr>
	<td>Paint</td>
	<td>42</td>
	<td>19.99975586</td>
	<td>ms</td>

</tr>
<tr>
	<td>Paint_avg</td>
	<td>0.823529412</td>
	<td>3.999951172</td>
	<td>ms</td>

</tr>
<tr>
	<td>Paint_count</td>
	<td>51</td>
	<td>5</td>
	<td>count</td>

</tr>
<tr>
	<td>Paint_max</td>
	<td>17.99975586</td>
	<td>13</td>
	<td>ms</td>

</tr>
<tr>
	<td>PaintSetup</td>
	<td>2.028808594</td>
	<td>1.038818359</td>
	<td>ms</td>

</tr>
<tr>
	<td>PaintSetup_avg</td>
	<td>0.225423177</td>
	<td>0.25970459</td>
	<td>ms</td>

</tr>
<tr>
	<td>PaintSetup_count</td>
	<td>9</td>
	<td>4</td>
	<td>count</td>

</tr>
<tr>
	<td>PaintSetup_max</td>
	<td>0.994140625</td>
	<td>0.740966797</td>
	<td>ms</td>

</tr>
<tr>
	<td>ParseHTML</td>
	<td>24</td>
	<td>20.99951172</td>
	<td>ms</td>

</tr>
<tr>
	<td>ParseHTML_avg</td>
	<td>2.181818182</td>
	<td>1.90904652</td>
	<td>ms</td>

</tr>
<tr>
	<td>ParseHTML_count</td>
	<td>11</td>
	<td>11</td>
	<td>count</td>

</tr>
<tr>
	<td>ParseHTML_max</td>
	<td>15.00024414</td>
	<td>13</td>
	<td>ms</td>

</tr>
<tr>
	<td>Program</td>
	<td>479.0021973</td>
	<td>474.001709</td>
	<td>ms</td>

</tr>
<tr>
	<td>Program_avg</td>
	<td>0.8330473</td>
	<td>0.793972712</td>
	<td>ms</td>

</tr>
<tr>
	<td>Program_count</td>
	<td>575</td>
	<td>597</td>
	<td>count</td>

</tr>
<tr>
	<td>Program_max</td>
	<td>168.9997559</td>
	<td>152</td>
	<td>ms</td>

</tr>
<tr>
	<td>RecalculateStyles</td>
	<td>17.00097656</td>
	<td>17.99926758</td>
	<td>ms</td>

</tr>
<tr>
	<td>RecalculateStyles_avg</td>
	<td>0.309108665</td>
	<td>0.183665996</td>
	<td>ms</td>

</tr>
<tr>
	<td>RecalculateStyles_count</td>
	<td>55</td>
	<td>98</td>
	<td>count</td>

</tr>
<tr>
	<td>RecalculateStyles_max</td>
	<td>3</td>
	<td>3</td>
	<td>ms</td>

</tr>
<tr>
	<td>TimerFire</td>
	<td>24.99975586</td>
	<td>25.00048828</td>
	<td>ms</td>

</tr>
<tr>
	<td>TimerFire_avg</td>
	<td>4.999951172</td>
	<td>6.25012207</td>
	<td>ms</td>

</tr>
<tr>
	<td>TimerFire_count</td>
	<td>5</td>
	<td>4</td>
	<td>count</td>

</tr>
<tr>
	<td>TimerFire_max</td>
	<td>20.99975586</td>
	<td>23</td>
	<td>ms</td>

</tr>
<tr>
	<td>XHRReadyStateChange</td>
	<td>3.000244141</td>
	<td>1</td>
	<td>ms</td>

</tr>
<tr>
	<td>XHRReadyStateChange_avg</td>
	<td>0.33336046</td>
	<td>0.111111111</td>
	<td>ms</td>

</tr>
<tr>
	<td>XHRReadyStateChange_count</td>
	<td>9</td>
	<td>9</td>
	<td>count</td>

</tr>
<tr>
	<td>XHRReadyStateChange_max</td>
	<td>1.000244141</td>
	<td>1</td>
	<td>ms</td>

</tr>
<tr>
	<td>jank</td>
	<td>29.40688608</td>
	<td>42.37636342</td>
	<td>ms</td>

</tr>
<tr>
	<td>mean_frame_time</td>
	<td>8.288616162</td>
	<td>8.029944445</td>
	<td>ms</td>

</tr>
<tr>
	<td>mostly_smooth</td>
	<td>17.62239996</td>
	<td>16.05000001</td>
	<td>percentile</td>

</tr>
<tr>
	<td>connectEnd</td>
	<td>2</td>
	<td>2</td>
	<td>ms</td>

</tr>
<tr>
	<td>connectStart</td>
	<td>0</td>
	<td>0</td>
	<td>ms</td>

</tr>
<tr>
	<td>domainLookupEnd</td>
	<td>1</td>
	<td>83</td>
	<td>ms</td>

</tr>
<tr>
	<td>domainLookupStart</td>
	<td>57</td>
	<td>63</td>
	<td>ms</td>

</tr>
<tr>
	<td>domComplete</td>
	<td>1083</td>
	<td>1737</td>
	<td>ms</td>

</tr>
<tr>
	<td>domContentLoadedEventEnd</td>
	<td>2</td>
	<td>3</td>
	<td>ms</td>

</tr>
<tr>
	<td>domContentLoadedEventStart</td>
	<td>0</td>
	<td>0</td>
	<td>ms</td>

</tr>
<tr>
	<td>domInteractive</td>
	<td>1623</td>
	<td>216</td>
	<td>ms</td>

</tr>
<tr>
	<td>domLoading</td>
	<td>7</td>
	<td>20</td>
	<td>ms</td>

</tr>
<tr>
	<td>fetchStart</td>
	<td>152</td>
	<td>81</td>
	<td>ms</td>

</tr>
<tr>
	<td>firstPaint</td>
	<td>5283.99992</td>
	<td>315.9999847</td>
	<td>ms</td>

</tr>
<tr>
	<td>loadEventEnd</td>
	<td>0</td>
	<td>0</td>
	<td>ms</td>

</tr>
<tr>
	<td>loadEventStart</td>
	<td>0</td>
	<td>0</td>
	<td>ms</td>

</tr>
<tr>
	<td>requestStart</td>
	<td>0</td>
	<td>0</td>
	<td>ms</td>

</tr>
<tr>
	<td>responseStart</td>
	<td>5149</td>
	<td>96</td>
	<td>ms</td>

</tr>
<tr>
	<td>droppedFrameCount</td>
	<td>8</td>
	<td>11</td>
	<td>count</td>
	
</tr>
<tr>
	<td>meanFrameTime</td>
	<td>17.79310345</td>
	<td>18.51851852</td>
	<td>ms</td>
	
</tr>
<tr>
	<td>numAnimationFrames</td>
	<td>86</td>
	<td>80</td>
	<td>count</td>
	
</tr>
<tr>
	<td>numFramesSentToScreen</td>
	<td>86</td>
	<td>80</td>
	<td>count</td>
	
</tr>
<tr>
	<td>ExpensiveEventHandlers</td>
	<td>1</td>
	<td>1</td>
	<td>count</td>

</tr>
<tr>
	<td>ExpensivePaints</td>
	<td>1</td>
	<td>0</td>
	<td>count</td>

</tr>
<tr>
	<td>GCInsideAnimation</td>
	<td>0</td>
	<td>0</td>
	<td>count</td>

</tr>
<tr>
	<td>Layers</td>
	<td>6</td>
	<td>2</td>
	<td>count</td>

</tr>
<tr>
	<td>NodePerLayout_avg</td>
	<td>66.66666667</td>
	<td>74.5</td>
	<td>count</td>

</tr>
<tr>
	<td>PaintedArea_avg</td>
	<td>9480.235294</td>
	<td>4950</td>
	<td>sq pixels</td>

</tr>
<tr>
	<td>PaintedArea_total</td>
	<td>483492</td>
	<td>24750</td>
	<td>sq pixels</td>
</tr>
Metric Color Change Opacity Change Unit
CompositeLayers 33.99902344 10.00048828 ms
require('browser-perf')('http://codepen.io/ariya/full/xuwgy', function(err, data) {
if (err) {
console.log(err);
} else {
console.log('Results');
for (var key in data[0]) {
var val = data[0][key];
console.log([key, val.value, val.unit, val.source].join());
}
}
}, {
browsers: 'chrome',
actions: function(browser) {
return browser.frame('result').then(function() {
return browser.execute('addOne()');
}).then(function() {
return browser.sleep(500);
});
},
log: console.log,
debug: true
});
{
"name": "GpuCompositiedcss",
"version": "0.0.0",
"main": "index.js",
"license": "Apache 2.0",
"dependencies": {
"browser-perf": "^0.1.13"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment