<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <id>https://web.dev/</id>
  <title>Colt McAnlis on web.dev</title>
  <updated>2026-04-15T23:21:06Z</updated>
  <author>
    <name>Colt McAnlis</name>
  </author>
  <link href="https://web.dev/authors/coltmcanlis/feed.xml" rel="self"/>
  <link href="https://web.dev/"/>
  <icon>https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/YT88zCOqYHewnehPUatW.png?auto=format</icon>
  <logo>https://web.dev/images/shared/rss-banner.png</logo>
  <subtitle>Developer Relations at Google</subtitle>
  
  
  <entry>
    <title>Static memory javascript with Object Pools</title>
    <link href="https://web.dev/speed-static-mem-pools/"/>
    <updated>2013-06-21T00:00:00Z</updated>
    <id>https://web.dev/speed-static-mem-pools/</id>
    <content type="html" mode="escaped">&lt;h2 id=&quot;introduction&quot;&gt;Introduction &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/speed-static-mem-pools/#introduction&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;So you get an email saying how your web-game / web-app is performing badly after a certain amount of time, you dig through your code, don’t see anything that stands out, until you open up Chrome’s memory performance tools, and see this:&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;A snapshot from your memory timeline&quot; decoding=&quot;async&quot; height=&quot;52&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 505px) 505px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/1IxMxMctbmXvdWAGdWPl.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/1IxMxMctbmXvdWAGdWPl.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/1IxMxMctbmXvdWAGdWPl.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/1IxMxMctbmXvdWAGdWPl.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/1IxMxMctbmXvdWAGdWPl.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/1IxMxMctbmXvdWAGdWPl.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/1IxMxMctbmXvdWAGdWPl.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/1IxMxMctbmXvdWAGdWPl.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/1IxMxMctbmXvdWAGdWPl.jpg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/1IxMxMctbmXvdWAGdWPl.jpg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/1IxMxMctbmXvdWAGdWPl.jpg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/1IxMxMctbmXvdWAGdWPl.jpg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/1IxMxMctbmXvdWAGdWPl.jpg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/1IxMxMctbmXvdWAGdWPl.jpg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/1IxMxMctbmXvdWAGdWPl.jpg?auto=format&amp;w=1010 1010w&quot; width=&quot;505&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;strong&gt;One of your co-workers chuckles, because they realize that you’ve got a memory-related performance problem.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In the memory graph view, this saw-tooth pattern is very telling about a potentially critical performance problem.  As your memory usage grows, you’ll see the chart area also grow in the timeline capture. When the chart dips suddenly, it’s an instance when the Garbage Collector has run, and cleaned up your referenced memory objects.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;What the Saw-Tooths mean&quot; decoding=&quot;async&quot; height=&quot;52&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 505px) 505px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/XGfgrWRgyDPsZStNWq4C.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/XGfgrWRgyDPsZStNWq4C.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/XGfgrWRgyDPsZStNWq4C.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/XGfgrWRgyDPsZStNWq4C.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/XGfgrWRgyDPsZStNWq4C.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/XGfgrWRgyDPsZStNWq4C.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/XGfgrWRgyDPsZStNWq4C.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/XGfgrWRgyDPsZStNWq4C.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/XGfgrWRgyDPsZStNWq4C.jpg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/XGfgrWRgyDPsZStNWq4C.jpg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/XGfgrWRgyDPsZStNWq4C.jpg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/XGfgrWRgyDPsZStNWq4C.jpg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/XGfgrWRgyDPsZStNWq4C.jpg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/XGfgrWRgyDPsZStNWq4C.jpg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/XGfgrWRgyDPsZStNWq4C.jpg?auto=format&amp;w=1010 1010w&quot; width=&quot;505&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;In a graph like this, you can see that there’s lots of Garbage Collection events occurring, which can be harmful to your web-apps’ performance. This article will talk about how to take control of your memory usage, reducing the impact on your performance.&lt;/p&gt;
&lt;h2 id=&quot;garbage-collection-and-performance-costs&quot;&gt;Garbage collection and performance costs &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/speed-static-mem-pools/#garbage-collection-and-performance-costs&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;JavaScript’s &lt;a href=&quot;http://en.wikipedia.org/wiki/Memory_model_(programming)&quot; rel=&quot;noopener&quot;&gt;memory model&lt;/a&gt; is built on a technology known as a &lt;a href=&quot;http://en.wikipedia.org/wiki/Garbage_collection_(computer_science)&quot; rel=&quot;noopener&quot;&gt;Garbage Collector&lt;/a&gt;. In many languages, the programmer is directly responsible for allocating and freeing memory from the system’s &lt;a href=&quot;https://en.wikipedia.org/wiki/Memory_management&quot; rel=&quot;noopener&quot;&gt;Memory Heap&lt;/a&gt;. A Garbage Collector system, however, manages this task on behalf of the programmer, meaning that objects aren’t directly freed from memory when the programmer dereferences it, but rather at a later time when the GC’s heuristics decide that it would be beneficial to do so. This decision process requires that the GC execute some statistical analysis on active and inactive objects, which takes a block of time to perform.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; In computer science, &lt;a href=&quot;http://en.wikipedia.org/wiki/Garbage_collection_(computer_science)&quot;&gt;Garbage Collector&lt;/a&gt; (GC) is a form of automatic memory management. The garbage collector attempts to reclaim garbage, or memory occupied by objects that are no longer in use by the program. &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;Garbage collection is often portrayed as the opposite of manual memory management, which requires the programmer to specify which objects to deallocate and return to the memory system&lt;/p&gt;
&lt;p&gt;The process in which a GC reclaims memory is not free, it usually cuts into your available performance by taking a block of time to do its work; alongside that, the system itself makes the decision when to run. You have no control over this action, a GC pulse can occur at any time during code execution, which will block code execution until it’s completed. The duration of this pulse is generally unknown to you; will take some amount of time to run, depending on how your program is utilizing memory at any given point.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Supercomputer&quot; rel=&quot;noopener&quot;&gt;High performance&lt;/a&gt; applications rely on consistent performance boundaries to ensure a smooth experience for users. Garbage collector systems can short circuit this goal, as they can run at random times for random durations, eating into the available time that the application needs to meet its performance goals.&lt;/p&gt;
&lt;h3 id=&quot;reduce-memory-churn,-reduce-garbage-collection-taxes&quot;&gt;Reduce Memory Churn, Reduce Garbage Collection taxes &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/speed-static-mem-pools/#reduce-memory-churn,-reduce-garbage-collection-taxes&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;As noted, a GC pulse will occur once a set of heuristics determines that there are enough inactive objects that a pulse would be beneficial. As such, the key to reducing the amount of time that the Garbage Collector takes from your application lies in eliminating as many cases of excessive object creation and release as you can. This process of creating/freeing object frequently is called “memory churn”. If you can reduce memory churn during the lifetime of your application, you also reduce the amount of time GC takes from your execution. This means you need to remove / reduce the number of created and destroyed objects, effectively, you have to stop allocating memory.&lt;/p&gt;
&lt;p&gt;This process will move your memory graph from this :&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;A snapshot from your memory timeline&quot; decoding=&quot;async&quot; height=&quot;52&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 505px) 505px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/1IxMxMctbmXvdWAGdWPl.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/1IxMxMctbmXvdWAGdWPl.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/1IxMxMctbmXvdWAGdWPl.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/1IxMxMctbmXvdWAGdWPl.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/1IxMxMctbmXvdWAGdWPl.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/1IxMxMctbmXvdWAGdWPl.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/1IxMxMctbmXvdWAGdWPl.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/1IxMxMctbmXvdWAGdWPl.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/1IxMxMctbmXvdWAGdWPl.jpg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/1IxMxMctbmXvdWAGdWPl.jpg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/1IxMxMctbmXvdWAGdWPl.jpg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/1IxMxMctbmXvdWAGdWPl.jpg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/1IxMxMctbmXvdWAGdWPl.jpg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/1IxMxMctbmXvdWAGdWPl.jpg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/1IxMxMctbmXvdWAGdWPl.jpg?auto=format&amp;w=1010 1010w&quot; width=&quot;505&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;to this:&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;Static Memory Javascript&quot; decoding=&quot;async&quot; height=&quot;53&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 505px) 505px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/3wPxsdOUhgx0AAEGo8jB.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/3wPxsdOUhgx0AAEGo8jB.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/3wPxsdOUhgx0AAEGo8jB.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/3wPxsdOUhgx0AAEGo8jB.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/3wPxsdOUhgx0AAEGo8jB.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/3wPxsdOUhgx0AAEGo8jB.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/3wPxsdOUhgx0AAEGo8jB.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/3wPxsdOUhgx0AAEGo8jB.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/3wPxsdOUhgx0AAEGo8jB.jpg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/3wPxsdOUhgx0AAEGo8jB.jpg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/3wPxsdOUhgx0AAEGo8jB.jpg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/3wPxsdOUhgx0AAEGo8jB.jpg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/3wPxsdOUhgx0AAEGo8jB.jpg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/3wPxsdOUhgx0AAEGo8jB.jpg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/3wPxsdOUhgx0AAEGo8jB.jpg?auto=format&amp;w=1010 1010w&quot; width=&quot;505&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;In this model, you can see that the graph no longer has a &lt;a href=&quot;http://en.wikipedia.org/wiki/Sawtooth_wave&quot; rel=&quot;noopener&quot;&gt;sawtooth&lt;/a&gt; like pattern, but rather grows a great deal in the beginning, and then slowly increases over time. If you’re running into performance problems due to memory churn, this is the type of graph you’ll want to create.&lt;/p&gt;
&lt;h2 id=&quot;moving-towards-static-memory-javascript&quot;&gt;Moving towards static-memory JavaScript &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/speed-static-mem-pools/#moving-towards-static-memory-javascript&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Static Memory JavaScript&lt;/strong&gt; is a technique which involves &lt;a href=&quot;http://en.wikipedia.org/wiki/Sawtooth_wave&quot; rel=&quot;noopener&quot;&gt;pre-allocating&lt;/a&gt;, at the start of your app, all the memory that will be needed for its lifetime, and managing that memory during execution as objects are no longer needed.
We can approach this goal in a few simple steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Instrument your application to determine what the maximum number of required live memory objects  (per type) are for a range of usage scenarios&lt;/li&gt;
&lt;li&gt;Re-implement your code to pre-allocate that maximum amount, and then manually  fetch/release them rather than going to main memory.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In reality, accomplishing #1 requires us to do a bit of #2, so let’s start there.&lt;/p&gt;
&lt;h3 id=&quot;object-pool&quot;&gt;Object Pool &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/speed-static-mem-pools/#object-pool&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In simple terms, &lt;a href=&quot;http://en.wikipedia.org/wiki/Object_pool_pattern&quot; rel=&quot;noopener&quot;&gt;object pooling&lt;/a&gt; is the process of retaining a set of unused objects which share a type. When you need a new object for your code, rather than allocating a new one from the system &lt;a href=&quot;https://en.wikipedia.org/wiki/Memory_management&quot; rel=&quot;noopener&quot;&gt;Memory Heap&lt;/a&gt;, you instead recycle one of the unused objects from the pool. Once the external code is done with the object, rather than releasing it to main memory, it is returned  to the pool. Because the object is never &lt;a href=&quot;http://en.wikipedia.org/wiki/Reference_(computer_science)&quot; rel=&quot;noopener&quot;&gt;dereferenced&lt;/a&gt; (aka deleted) from code it won’t be garbage collected. &lt;strong&gt;Utilizing object pools puts control of memory back in the hands of the programmer, reducing the influence of the garbage collector on performance.&lt;/strong&gt;&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; Object pools are a common practice in many high performance applications, as they reduce the amount of memory churn that is placed on the system. Object pools themselves have two primary characteristics:  1. A pool will continue to grow in memory footprint as the number as live objects increases. 1. The number of created/released object per-frame will drop to the minimum required by your application.  &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;Since there’s a heterogenous set of object types that an application maintains, proper usage of object pools requires you to have one pool per type that experiences high-churn during your application’s runtime.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; newEntity &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; gEntityObjectPool&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;allocate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;newEntity&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;pos &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token literal-property property&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;215&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;88&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;//..... do some stuff with the object that we need to do&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;gEntityObjectPool&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;free&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;newEntity&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;//free the object when we&#39;re done&lt;/span&gt;&lt;br /&gt;newEntity &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;//free this object reference&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;For the large majority of applications, you’ll eventually hit some level-off in terms of needing to allocate new objects. Over multiple runs of your application, you should be able to get a great feel for what this upper limit is, and can pre-allocate that number of objects at the start of your application.&lt;/p&gt;
&lt;h3 id=&quot;pre-allocating-objects&quot;&gt;Pre-allocating objects &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/speed-static-mem-pools/#pre-allocating-objects&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Implementing object pooling into your project will give you a theoretical maximum for the number of objects required during the runtime of your application. Once running your site through various testing scenarios, you can get a good sense of the types of memory requirements that will be needed, and can catalog that data somewhere, and analyze it to understand what the upper limits of memory requirements are for your application.&lt;/p&gt;
&lt;p&gt;Then, in the shipping version of your app, you can set the initialization phase to pre-fill all the object pools to a specified amount. This act will push all the object initialization to the front of your app, and reduce the amount of allocations that occur dynamically during its execution.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;//preallocate all our pools. &lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;//Note that we keep each pool homogeneous wrt object types&lt;/span&gt;&lt;br /&gt;  gEntityObjectPool&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;preAllocate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;256&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  gDomObjectPool&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;preAllocate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;888&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;The amount you choose has a great deal to do with the behavior of your application; sometimes the theoretical maximum isn’t the best option. For instance, choosing the average maximum may give you a smaller memory footprint for non power-users.&lt;/p&gt;
&lt;h3 id=&quot;far-from-a-silver-bullet&quot;&gt;Far from a silver bullet &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/speed-static-mem-pools/#far-from-a-silver-bullet&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;There’s a whole classification of apps in which static memory growth patterns can be a win. As fellow Chrome DevRel &lt;a href=&quot;https://plus.google.com/u/0/+RenatoMangini/posts&quot; rel=&quot;noopener&quot;&gt;Renato Mangini&lt;/a&gt; points out however, there are a few drawbacks.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; Pools are not for everyone, even on high-performance apps. Consider the following tradeoffs before adopting object pools and static memory methods: Startup time will be longer, since you’re spending cycles allocating memory at initialization time. Memory doesn’t shrink in low-usage scenarios; Your app will greedily consume memory. You’ll sometimes need to clean an object when it’s returned to the pool, this can have a non-trivial overhead associated with it during high-memory-churn areas. &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/speed-static-mem-pools/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;One of the reasons that JavaScript is ideal for the web relies on the fact it’s a fast, fun and easy language to get started with. This is mainly due to its low barrier to syntax restrictions and its handling of the memory issues on your behalf. You can code away and let it take care of the dirty work.
However for high-performance web applications, like &lt;a href=&quot;https://www.udacity.com/course/cs255&quot; rel=&quot;noopener&quot;&gt;HTML5 games&lt;/a&gt;, the GC can often eat away at critically needed &lt;a href=&quot;http://en.wikipedia.org/wiki/Frame_rate&quot; rel=&quot;noopener&quot;&gt;frame rate&lt;/a&gt;, reducing the experience for the end user. With some careful instrumentation and adoption of object pools, you can reduce this burden on your frame rate, and reclaim that time for more awesome things.&lt;/p&gt;
&lt;h2 id=&quot;source-code&quot;&gt;Source Code &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/speed-static-mem-pools/#source-code&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There are lots of implementations of object pools floating around on the web, so I won’t bore you with yet another one. Instead, I’ll direct you to these, each of which has specific implementation nuances; which is important, considering that each application usage may have specific implementation needs.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/playcraft/gamecore.js/blob/master/src/pooled.js&quot; rel=&quot;noopener&quot;&gt;Gamecore.js’ object pool&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://beej.us/blog/data/object-pool/&quot; rel=&quot;noopener&quot;&gt;Beej’s Object Pools&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/emehrkay/Pool&quot; rel=&quot;noopener&quot;&gt;Emehrkay’s super simple object pool&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://blog.sklambert.com/javascript-object-pool/&quot; rel=&quot;noopener&quot;&gt;Steven Lambert’s game-focused object pool&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://code.google.com/p/renderengine/wiki/ObjectPooling&quot; rel=&quot;noopener&quot;&gt;RenderEngine’s objectPool setup&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;references&quot;&gt;References &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/speed-static-mem-pools/#references&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://buildnewgames.com/garbage-collector-friendly-code/&quot; rel=&quot;noopener&quot;&gt;Garbage Collector Friendly Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://addyosmani.com/blog/taming-the-unicorn-easing-Javascript-memory-profiling-in-devtools/&quot; rel=&quot;noopener&quot;&gt;Taming the unicorn : easing Javascript memory profiling in devtools&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://coding.smashingmagazine.com/2012/11/05/writing-fast-memory-efficient-Javascript/#more-123093&quot; rel=&quot;noopener&quot;&gt;Writing fast, memory efficient javascript&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    <author>
      <name>Colt McAnlis</name>
    </author>
  </entry>
  
  <entry>
    <title>CSS paint times and page render weight</title>
    <link href="https://web.dev/css-paint-times/"/>
    <updated>2013-04-12T00:00:00Z</updated>
    <id>https://web.dev/css-paint-times/</id>
    <content type="html" mode="escaped">&lt;aside class=&quot;aside flow bg-state-warn-bg color-state-warn-text&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block color-state-warn-text&quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; role=&quot;img&quot; aria-label=&quot;Warning sign&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M23 21L12 2 1 21h22zm-12-3v-2h2v2h-2zm0-4h2v-4h-2v4z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Warning&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; This article contains numeric evaluation from a specific build of a browser. Over time, these numbers will change, as will the data provided here. &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;introduction&quot;&gt;Introduction &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/css-paint-times/#introduction&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you’re the type of person who keeps up with things like &lt;a href=&quot;http://www.html5rocks.com/en/tutorials/internals/howbrowserswork/&quot; rel=&quot;noopener&quot;&gt;how browsers work&lt;/a&gt;, then you already know that there’s been some amazing articles lately detailing Chrome’s GPU accelerated renderer/composite operation. Firstly &lt;a href=&quot;http://www.html5rocks.com/en/tutorials/speed/layers/&quot; rel=&quot;noopener&quot;&gt;Accelerated Rendering in Chrome: The Layer Model&lt;/a&gt; is a great introduction to how Chrome uses the concept of layers to draw their page; and for a deeper dive &lt;a href=&quot;http://www.chromium.org/developers/design-documents/gpu-accelerated-compositing-in-chrome&quot; rel=&quot;noopener&quot;&gt;GPU Accelerated Compositing in Chrome&lt;/a&gt; discusses how Chrome uses these layers, alongside the GPU for rendering your page.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; The quick version of these articles is that the hardware accelerated path in Chrome will &lt;strong&gt;Paint&lt;/strong&gt; 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 &lt;strong&gt;Compositing&lt;/strong&gt;. Chrome will move the tiles in and out of memory based upon need and performance heuristics that can change between platforms. &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;the-philosophical-question&quot;&gt;The philosophical question &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/css-paint-times/#the-philosophical-question&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Having spent a great deal of time writing &lt;a href=&quot;http://en.wikipedia.org/wiki/Software_rendering&quot; rel=&quot;noopener&quot;&gt;software rasterizers&lt;/a&gt; for 3D purposes, it became apparent in my mind that some &lt;a href=&quot;http://docs.webplatform.org/wiki/css/properties&quot; rel=&quot;noopener&quot;&gt;CSS properties&lt;/a&gt; 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: &lt;strong&gt;How do different CSS properties affect the render-weight of your page?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;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:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Generate a suite of individual HTML pages; each one with a single DOM element and some permutation of CSS properties attached to it.&lt;/li&gt;
&lt;li&gt;Run some automation script that, for each page, will:
&lt;ul&gt;
&lt;li&gt;Launch Chrome&lt;/li&gt;
&lt;li&gt;Load a page&lt;/li&gt;
&lt;li&gt;Produce a &lt;a href=&quot;https://sites.google.com/site/skiadocs/developer-documentation/skia-debugger&quot; rel=&quot;noopener&quot;&gt;Skia Picture&lt;/a&gt; for the page&lt;/li&gt;
&lt;li&gt;Run each Skia Picture taken through &lt;a href=&quot;https://sites.google.com/site/skiadocs/developer-documentation/skia-debugger&quot; rel=&quot;noopener&quot;&gt;Skia Benchmark&lt;/a&gt; to obtain timings&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Dump out all the timings, and marvel at the numbers. (This part is important…)&lt;/li&gt;
&lt;/ul&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; Chrome’s software rasterizer package is called &lt;a href=&quot;http://www.chromium.org/developers/design-documents/graphics-and-skia&quot;&gt;SKIA&lt;/a&gt;, and it not only handles rasterization of your web page, but also all your HTML5 Canvas API needs (Boxes, lines, bitmap fills, drop shadows, blurs, all the calls Chrome needs to turn your DOM into pixels). In order to help debugging the rendering of a page, SKIA allows you save out &lt;a href=&quot;https://sites.google.com/site/skiadocs/developer-documentation/skia-debugger&quot;&gt;Skia Picture (*.SKP)&lt;/a&gt; files which record all the commands used to paint the page. &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;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:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;style&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token style&quot;&gt;&lt;span class=&quot;token language-css&quot;&gt;&lt;br /&gt;&lt;span class=&quot;token selector&quot;&gt;#example1&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token url&quot;&gt;&lt;span class=&quot;token function&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;foo.png&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; top left / 50% 60%&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 20px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;margin-top&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 10px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;margin-right&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 20px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;text-align&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; center&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;style&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;example1&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;WOAH&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;And another, that’s more complex&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;style&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token style&quot;&gt;&lt;span class=&quot;token language-css&quot;&gt;&lt;br /&gt;&lt;span class=&quot;token selector&quot;&gt;#example1&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;background-color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;#eee&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;box-shadow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1px 2px 3px 4px black&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;border-radius&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 50%&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;radial-gradient&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;circle closest-corner&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; white&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; black&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 20px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;margin-top&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 10px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;margin-right&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 20px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;text-align&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; center&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;style&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;example1&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;WOAH&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Below, as a variant of the last example, where we only change the radial-gradient value:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;style&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token style&quot;&gt;&lt;span class=&quot;token language-css&quot;&gt;&lt;br /&gt;&lt;span class=&quot;token selector&quot;&gt;#example1&lt;/span&gt; &lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;background-color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;#eee&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;box-shadow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1px 2px 3px 4px black&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;border-radius&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 50%&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;radial-gradient&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;farthest-side&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; white&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; black&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 20px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;margin-top&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 10px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;margin-right&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 20px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;text-align&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; center&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;style&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;example1&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token special-attr&quot;&gt;&lt;span class=&quot;token attr-name&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token value css language-css&quot;&gt;&lt;span class=&quot;token property&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 20px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;margin-top&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 10px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;margin-right&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 20px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;text-align&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; center&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;WOAH&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Each page is then loaded into a &lt;strong&gt;fresh&lt;/strong&gt; instance of Chrome (to ensure that timings weren’t somehow biased by any stale states in page reloads), and a &lt;a href=&quot;https://sites.google.com/site/skiadocs/developer-documentation/skia-debugger&quot; rel=&quot;noopener&quot;&gt;Skia Picture (*.SKP)&lt;/a&gt; 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 &lt;a href=&quot;https://code.google.com/p/skia/&quot; rel=&quot;noopener&quot;&gt;Skia source code&lt;/a&gt;) which dumps out the average time taken to render that page.&lt;/p&gt;
&lt;h3 id=&quot;evaluating-the-data&quot;&gt;Evaluating the data &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/css-paint-times/#evaluating-the-data&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;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 &lt;a href=&quot;https://www.google.com/intl/en/chrome/browser/beta.html&quot; rel=&quot;noopener&quot;&gt;Chrome 27 beta&lt;/a&gt;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.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Timings for all permutations in the test&quot; decoding=&quot;async&quot; height=&quot;417&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/MNzI5WIQyIlDKm11nlK2.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/MNzI5WIQyIlDKm11nlK2.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/MNzI5WIQyIlDKm11nlK2.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/MNzI5WIQyIlDKm11nlK2.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/MNzI5WIQyIlDKm11nlK2.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/MNzI5WIQyIlDKm11nlK2.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/MNzI5WIQyIlDKm11nlK2.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/MNzI5WIQyIlDKm11nlK2.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/MNzI5WIQyIlDKm11nlK2.jpg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/MNzI5WIQyIlDKm11nlK2.jpg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/MNzI5WIQyIlDKm11nlK2.jpg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/MNzI5WIQyIlDKm11nlK2.jpg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/MNzI5WIQyIlDKm11nlK2.jpg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/MNzI5WIQyIlDKm11nlK2.jpg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/MNzI5WIQyIlDKm11nlK2.jpg?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/MNzI5WIQyIlDKm11nlK2.jpg?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/MNzI5WIQyIlDKm11nlK2.jpg?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/MNzI5WIQyIlDKm11nlK2.jpg?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;p&gt;Firstly we find proof that &lt;strong&gt;some CSS properties are just plain more expensive to render than others&lt;/strong&gt;. 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.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Time taken to paint an element that has only 1 CSS property on it&quot; decoding=&quot;async&quot; height=&quot;378&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/itmfP4UqdMNLZbtpErlH.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/itmfP4UqdMNLZbtpErlH.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/itmfP4UqdMNLZbtpErlH.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/itmfP4UqdMNLZbtpErlH.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/itmfP4UqdMNLZbtpErlH.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/itmfP4UqdMNLZbtpErlH.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/itmfP4UqdMNLZbtpErlH.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/itmfP4UqdMNLZbtpErlH.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/itmfP4UqdMNLZbtpErlH.jpg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/itmfP4UqdMNLZbtpErlH.jpg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/itmfP4UqdMNLZbtpErlH.jpg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/itmfP4UqdMNLZbtpErlH.jpg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/itmfP4UqdMNLZbtpErlH.jpg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/itmfP4UqdMNLZbtpErlH.jpg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/itmfP4UqdMNLZbtpErlH.jpg?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/itmfP4UqdMNLZbtpErlH.jpg?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/itmfP4UqdMNLZbtpErlH.jpg?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/itmfP4UqdMNLZbtpErlH.jpg?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;Secondly, and more interestingly, &lt;strong&gt;combinations of CSS Properties can have a greater paint time than the sum of their parts&lt;/strong&gt;. From an observer’s perspective, this is a bit odd, we’d expect that A+B = C, not 2.2C. For example adding &lt;code&gt;box-shadow&lt;/code&gt; and &lt;code&gt;border-radius-stroke&lt;/code&gt; :&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Timings for all permutations in the test&quot; decoding=&quot;async&quot; height=&quot;294&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 306px) 306px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/10tVfwX1pZYNgJQjQRhm.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/10tVfwX1pZYNgJQjQRhm.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/10tVfwX1pZYNgJQjQRhm.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/10tVfwX1pZYNgJQjQRhm.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/10tVfwX1pZYNgJQjQRhm.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/10tVfwX1pZYNgJQjQRhm.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/10tVfwX1pZYNgJQjQRhm.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/10tVfwX1pZYNgJQjQRhm.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/10tVfwX1pZYNgJQjQRhm.jpg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/10tVfwX1pZYNgJQjQRhm.jpg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/10tVfwX1pZYNgJQjQRhm.jpg?auto=format&amp;w=612 612w&quot; width=&quot;306&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;strong&gt;What’s really interesting about this, is that it’s not just the &lt;code&gt;box-shadow&lt;/code&gt; property itself, but rather &lt;i&gt;that specific value permutation&lt;/i&gt;.&lt;/strong&gt; For example, below shows a grouping of &lt;code&gt;box-shadow : 50%&lt;/code&gt; and &lt;code&gt;border-radius&lt;/code&gt; with value variations.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Timings for all permutations in the test&quot; decoding=&quot;async&quot; height=&quot;304&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 505px) 505px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/GKt6hjihzXM31TA7UHBG.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/GKt6hjihzXM31TA7UHBG.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/GKt6hjihzXM31TA7UHBG.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/GKt6hjihzXM31TA7UHBG.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/GKt6hjihzXM31TA7UHBG.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/GKt6hjihzXM31TA7UHBG.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/GKt6hjihzXM31TA7UHBG.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/GKt6hjihzXM31TA7UHBG.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/GKt6hjihzXM31TA7UHBG.jpg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/GKt6hjihzXM31TA7UHBG.jpg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/GKt6hjihzXM31TA7UHBG.jpg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/GKt6hjihzXM31TA7UHBG.jpg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/GKt6hjihzXM31TA7UHBG.jpg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/GKt6hjihzXM31TA7UHBG.jpg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/GKt6hjihzXM31TA7UHBG.jpg?auto=format&amp;w=1010 1010w&quot; width=&quot;505&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;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&lt;/p&gt;
&lt;h2 id=&quot;finding-your-page-render-weight&quot;&gt;Finding your page render-weight &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/css-paint-times/#finding-your-page-render-weight&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;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; Here’s a couple tips to get started&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Use Chrome’s &lt;a href=&quot;http://updates.html5rocks.com/2013/02/Profiling-Long-Paint-Times-with-DevTools-Continuous-Painting-Mode&quot; rel=&quot;noopener&quot;&gt;Continuous Paint mode&lt;/a&gt; in Chrome Dev Tools to get an understanding of what CSS properties are costing you.&lt;/li&gt;
&lt;li&gt;Incorporate CSS reviews into your existing code review process to catch performance issues
Look for places in your CSS where you are using things that are known to be more expensive, like gradients and shadows. Ask yourself, do I really need these here?&lt;/li&gt;
&lt;li&gt;When in doubt, always err on the side of better performance. Your users may not remember what the padding width is on your columns, but they will remember how it feels to visit your site.&lt;/li&gt;
&lt;/ol&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; Unfortunately, without a custom timing setup like the one built, it’s currently difficult to automate the process of finding page render-weight, which makes it difficult to embrace continuous integration for your page builds across platforms. &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;final-thoughts&quot;&gt;Final Thoughts &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/css-paint-times/#final-thoughts&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;One of the most interesting things about this experiment is that the timings will continue to change with each &lt;a href=&quot;https://www.google.com/intl/en/chrome/browser/beta.html&quot; rel=&quot;noopener&quot;&gt;version of Chrome&lt;/a&gt; (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 &lt;code&gt;box-shadow: 1px 2px 3px 4px&lt;/code&gt; an an element that already has &lt;code&gt;border-radius:5&lt;/code&gt;. &lt;strong&gt;However the more valuable takeaway should be that CSS properties directly affect your page paint times.&lt;/strong&gt;&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; 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. &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;references&quot;&gt;References &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/css-paint-times/#references&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.html5rocks.com/en/tutorials/internals/howbrowserswork/&quot; rel=&quot;noopener&quot;&gt;How browsers work&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.html5rocks.com/en/tutorials/speed/layers/&quot; rel=&quot;noopener&quot;&gt;Accelerated Rendering in Chrome: The Layer Model&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.chromium.org/developers/design-documents/gpu-accelerated-compositing-in-chrome&quot; rel=&quot;noopener&quot;&gt;GPU Accelerated Compositing in Chrome&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://code.google.com/p/skia/&quot; rel=&quot;noopener&quot;&gt;Skia source code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://sites.google.com/site/skiadocs/developer-documentation/skia-debugger&quot; rel=&quot;noopener&quot;&gt;Skia Debugger&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.chromium.org/developers/design-documents/gpu-accelerated-compositing-in-chrome&quot; rel=&quot;noopener&quot;&gt;GPU Accelerated Compositing in Chrome&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://updates.html5rocks.com/2013/02/Profiling-Long-Paint-Times-with-DevTools-Continuous-Painting-Mode&quot; rel=&quot;noopener&quot;&gt;Chrome DevTools : Continuous Paint mode&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    <author>
      <name>Colt McAnlis</name>
    </author>
  </entry>
</feed>
