Skip to content
This repository has been archived by the owner on Jan 22, 2024. It is now read-only.

Commit

Permalink
Merge pull request #336 from mainroach/master
Browse files Browse the repository at this point in the history
Add "CSS Paint times and page Render Weight" tutorial
  • Loading branch information
adanilo committed Apr 4, 2013
2 parents f1a58b4 + f2e07c2 commit f7f8b89
Show file tree
Hide file tree
Showing 11 changed files with 244 additions and 1 deletion.
211 changes: 211 additions & 0 deletions content/tutorials/speed/css-paint-times/en/index.html
@@ -0,0 +1,211 @@

{% extends "tutorial.html" %}
{% load mixin from templatefilters %}

{% block pagebreadcrumb %}{{ tut.title }}{% endblock %}

{% block head %}
<style>
.talkinghead:before {
background-image: url(/static/images/profiles/75/duhroach.75.png);
background-position: 0px 0px !important;
}
article.tutorial .notice.fact {
position: relative;
padding-left: 25px;
}
article.tutorial .notice.fact:before {
position: absolute;
top: -5px;
left: -10px;
text-transform: uppercase;
-webkit-transform: rotateZ(-30deg);
-moz-transform: rotateZ(-30deg);
-o-transform: rotateZ(-30deg);
-ms-transform: rotateZ(-30deg);
transform: rotateZ(-30deg);
/*color: rgb(80, 139, 136);*/
color: rgb(237, 71, 50);
font-weight: bold;
content: "Fact";
}

</style>
{% endblock %}

{% block iscompatible %}
{% endblock %}

{% block html5badge %}
<!-- Your HTML5 badge (tech class icons used in the article) goes here -->
{% endblock %}

{% block share_image %}
<!--<meta itemprop="image" content="images/your_social_sharing_img.png">-->
{% endblock %}


{% block content %}
<p class="notice">
<b>NOTE:</b>This article contains numeric evaluation from a specific build of a browser. Over time, these numbers will change, as will the data provided here.</p>

<h2 id="toc-introduction">Introduction</h2>

<p>If you’re the type of person who keeps up with things like <a href="http://www.html5rocks.com/en/tutorials/internals/howbrowserswork/" target="_blank">how browsers work</a>, then you already know that there’s been some amazing articles lately detailing Chrome’s GPU accelerated renderer/composite operation. Firstly <a href="http://www.html5rocks.com/en/tutorials/speed/layers/" target="_blank">Accelerated Rendering in Chrome: The Layer Model</a> is a great introduction to how Chrome uses the concept of layers to draw their page; and for a deeper dive <a href="http://www.chromium.org/developers/design-documents/gpu-accelerated-compositing-in-chrome" target="_blank">GPU Accelerated Compositing in Chrome</a> discusses how Chrome uses these layers, alongside the GPU for rendering your page.
</p>

<blockquote class="commentary talkinghead" id="how-works">
The quick version of these articles is that the hardware accelerated path in chrome will <b>Paint</b> your page by rasterizing the page visuals into tiles. These tiles are then passed off to the GPU, where the hardware will do the final drawing of tiles to the screen, a process known as <b>Compositing</b>. Chrome will move the tiles in and out of memory based upon need and performance heuristics that can change between platforms.

</blockquote>


<h2 id="toc-topic">The philosophical question</h2>
<p>
Having spent a great deal of time writing <a href="http://en.wikipedia.org/wiki/Software_rendering" target="_blank">software rasterizers</a> for 3D purposes, it became apparent in my mind that some <a href="http://docs.webplatform.org/wiki/css/properties" target="_blank">CSS properties</a> should have varied performance when drawing your page. For example, rasterizing a small image to the screen is a completely different algorithmic operation that drawing a drop shadow on an arbitrary shape. So the question became: <b>How do different CSS properties affect the render-weight of your page?</b>
</p>

<p>
My goal was to categorize a large set of CSS properties/values by their paint times, so that we can create an understanding of what types of CSS properties are more performant than others. To do this, I wrote some automation with duct-tape and bubble gum to attempt to add numerical visibility to CSS paint times, which worked like this:

<ul>
<li>Generate a suite of individual HTML pages; each one with a single DOM element and some permutation of CSS properties attached to it. </li>
<li>Run some automation script that, for each page, will:
<ul>
<li>Launch Chrome </li>
<li>Load a page </li>
<li>Produce a <a href="https://sites.google.com/site/skiadocs/developer-documentation/skia-debugger" target="_blank">Skia Picture</a> for the page </li>
<li>Run each Skia Picture taken through <a href="https://sites.google.com/site/skiadocs/developer-documentation/skia-debugger" target="_blank">Skia Benchmark</a> to obtain timings </li>
</ul>
</li>
<li>Dump out all the timings, and marvel at the numbers. (This part is important..)</li>
</ul>









With this setup, we generate a suite of HTML pages, where each page contains a unique permutation of CSS properties and values; for instance, here’s two html files:
</p>

<pre class="prettyprint">
&lt;style>
#example1 {
background: url(foo.png) top left / 50% 60%;
padding: 20px;
margin-top: 10px;
margin-right: 20px;
text-align: center;
}
&lt;/style>
&lt;div id="example1">WOAH&lt;/div>
</pre>

<p>And another, that’s more complex</p>
<pre class="prettyprint">
&lt;style>
#example1 {
background-color:#eee;
box-shadow: 1px 2px 3px 4px black;
border-radius: 50%;
<b>background: radial-gradient(circle closest-corner, white, black);</b>
padding: 20px;
margin-top: 10px;
margin-right: 20px;
text-align: center;
}
&lt;/style>
&lt;div id="example1">WOAH&lt;/div>

</pre>

<p>Below, as a variant of the last example, where we only change the radial-gradient value:</p>

<pre class="prettyprint">
&lt;style>
#example1
{
background-color:#eee;
box-shadow: 1px 2px 3px 4px black;
border-radius: 50%;
<b>background: radial-gradient(farthest-side, white, black);</b>
padding: 20px;
margin-top: 10px;
margin-right: 20px;
text-align: center;
}
&lt;/style>
&lt;div id="example1" style="padding: 20px; margin-top: 10px;margin-right: 20px; text-align: center;">WOAH&lt;/div>
</pre>

<p>Each page is then loaded into a <b>fresh</b> instance of Chrome (to ensure that timings weren’t somehow biased by any stale states in page reloads), and a <a href="https://sites.google.com/site/skiadocs/developer-documentation/skia-debugger ">Skia Picture (*.SKP)</a> is taken to evaluate what Skia commands are used to paint the page. Once SKP files have been generated for each HTML file, we run another batch to push the *.SKP files through the Skia Benchmark application (built from the <a href="https://code.google.com/p/skia/">Skia source code</a>) which dumps out the average time taken to render that page.
</p>

<h3 id="toc-topic">Evaluating the data</h3>

<p>From this, we now have some rough ability to chart how much a suite of CSS properties take to paint. Or rather, we can start stack-ranking CSS properties by their paint performance. Here’s a large graph taken with <a href="https://www.google.com/intl/en/chrome/browser/beta.html" target="_blank">Chrome 27 beta </a>showing off all the full set of timing data from this process. Note that all data is subject to change as Chrome becomes faster and faster with time.
</p>

<CENTER>
<a target="_blank" href="cssTimesDetail.jpg"><img src="sm_cssTimesDetail.jpg" title="Timings for all permutations in the test" alt="Timings for all permutations in the test"></a>
</center>

<p>Each vertical bar represents the paint-time of a page with a single combination of CSS properties, (magnified by 100x; True-scale value of this graph is [0,1.56ms]). Lots of pretty lines, but in this form it’s somewhat useless; we need to do some data mining to find useful trends.</p>

<p>Firstly we find proof that <b>some CSS properties are just plain more expensive to render than others</b>. For example, drawing a drop-shadow on a DOM element involves a multi-pass operation with splines and other sorts of nasty things, as opposed to opacity which should be easier to render.
</p>

<center>
<a target="_blank" href="cssTimesSingles.jpg"><img src="sm_cssTimesSingles.jpg" title=" Time taken to paint an element that has only 1 CSS property on it" alt=" Time taken to paint an element that has only 1 CSS property on it"></a>
</center>

<p>
Secondly, and more interestingly, <b>combinations of CSS Properties can have a greater paint time than the sum of their parts</b>. From an observer’s perspective, this is a bit odd, we’d expect that A+B = C, not 2.2C. For example adding <code>box-shadow</code> and <code>border-radius-stroke</code> :
</p>

<CENTER>
<img src="figure2.jpg" title="Timings for all permutations in the test" alt="Timings for all permutations in the test">
</center>

<p>
<b>What’s really interesting about this, is that it’s not just the <code>box-shadow</code> property itself, but rather <i>that specific value permutation</i>.</b> For example, below shows a grouping of <code>box-shadow : 50%</code> and <code>border-radius</code> with value variations.
</p>
<CENTER>
<img src="figure3.jpg" title="Timings for all permutations in the test" alt="Timings for all permutations in the test">
</center>

<p>
Looking at the data, this goes on for a while. There’s lots of various odd combinations, and my test suite hardly touches them all; there’s still tons of tests and combinations that could yield interesting results</p>

<h2 id="toc-final">Know your pages' render-weight</h2>
<p>
Armed with the ability to track the render times for each element on your page, developers have the ability to start evaluating their page-render-weight, and how it affects the responsiveness of your site. </p>

<blockquote class="commentary talkinghead" id="how-works">
Unfortunately, without a custom timing setup like the one built, it’s currently difficult to automate the process of finding page render-weight. At the time of this article writing, one of the primary ways to find render-weights for elements on your page is to use the <a href="http://updates.html5rocks.com/2013/02/Profiling-Long-Paint-Times-with-DevTools-Continuous-Painting-Mode" target="_blank">Continuous Paint mode</a> in Chrome Dev Tools, which with a little manual intervention, allows you to get a rough estimate on what elements on your page can be slower than others.
</blockquote>
<p>
One of the most interesting things about this experiment is that the timings will continue to change with each <a href="https://www.google.com/intl/en/chrome/browser/beta.html" target="_blank">version of Chrome</a> (hopefully getting faster ;) browser software is an ever-changing surface area. What’s slow today, could be fast tomorrow. You could take away from this article to avoid putting <code>box-shadow 1px 2px 3px 4px</code> an an element that already has <code>border-radius:5</code>. However the more valuable takeaway should be that CSS properties directly affect your page paint times.</p>

<p class="notice fact">
As with any software, make sure to test all design choices against your performance targets and platforms to determine validity in your own applications before making design decisions.
</p>



<h2 id="toc-references">References</h2>
<ul>
<li><a href="http://www.html5rocks.com/en/tutorials/internals/howbrowserswork/" target="_blank">How browsers work</a></li>
<li> <a href="http://www.html5rocks.com/en/tutorials/speed/layers/" target="_blank">Accelerated Rendering in Chrome: The Layer Model</a></li>
<li><a href="http://www.chromium.org/developers/design-documents/gpu-accelerated-compositing-in-chrome" target="_blank">GPU Accelerated Compositing in Chrome</a></li>
<li><a href="https://code.google.com/p/skia/">Skia source code</a> </li>
<li><a href="https://sites.google.com/site/skiadocs/developer-documentation/skia-debugger ">Skia Debugger</a></li>
<li><a href="http://www.chromium.org/developers/design-documents/gpu-accelerated-compositing-in-chrome" target="_blank">GPU Accelerated Compositing in Chrome</a></li>
<li><a href="http://updates.html5rocks.com/2013/02/Profiling-Long-Paint-Times-with-DevTools-Continuous-Painting-Mode" target="_blank">Chrome DevTools : Continuous Paint mode</a></li>
</ul>

{% endblock %}
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
19 changes: 19 additions & 0 deletions database/profiles.yaml
Expand Up @@ -1198,3 +1198,22 @@ google: 100684278618967844344
twitter: unit9
email: developers@unit9.com

---

id: duhroach
name:
given: Colt
family: McAnlis
org:
name: Google
unit: Developer Relations
address:
locality: Mountain View
region: California
country: USA
lat: 37.8575592041016
lon: -122.241989135742
homepage: http://mainroach.blogspot.com
google: +ColtMcAnlis
twitter: duhroach
email: colton@google.com
15 changes: 14 additions & 1 deletion database/tutorials.yaml
Expand Up @@ -16,7 +16,20 @@ tags:
- class:nuts_and_bolts

---

title: CSS Paint times and page Render Weight
url: /tutorials/speed/css-paint-times/
author_id: duhroach
publication_date: 2013-04-03
description: Understanding how difference CSS property combinations can influence the paint-time of your page
browser_support:
- chrome
tags:
- css
- render
- class:performance
- type:tutorial

---
title: "CSS Masking"
url: /tutorials/masking/adobe/
author_id: dschulze
Expand Down
Binary file added static/images/profiles/75/duhroach.75.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added static/images/profiles/duhroach.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit f7f8b89

Please sign in to comment.