HTML5 Rocks

HTML5 Rocks

requestAnimationFrame API: now with sub-millisecond precision

By Paul Irish at

If you've been using requestAnimationFrame you've enjoyed seeing your paints synchronized to the refresh rate of the screen, resulting in the most high-fidelity animations possible. Plus, you're saving your users CPU fan noise and battery-power when they switch to another tab.

There is about to be a change to part of the API, however. The Timestamp that is passed into your callback function is changing from a typical Date.now()-like timestamp to a high-resolution measurement of floating point milliseconds since the page was opened. If you use this value, you will need to update your code, based on the explanation below.

Just to be clear, here is what I'm talking about:

   // assuming requestAnimationFrame method has been normalized for all vendor prefixes..
   requestAnimationFrame(function(timestamp){
       // the value of timestamp is changing
   });
   

If you're using the common requestAnimFrame shim provided here, then you're not using the timestamp value. You're off the hook. :)

Why

Why? Well rAF helps you get the ultimate 60 fps that is ideal, and 60 fps translates to 16.7ms per frame. But measuring with integer milliseconds means we have a precision of 1/16 for everything we want to observe and target.

As you can see above, the blue bar represents the maximum amount of time you have to do all your work before you paint a new frame (at 60fps). You're probably doing more than 16 things, but with integer milliseconds you only have the ability to schedule and measure in those very chunky increments. That's not good enough.

The High Resolution Timer solves this by providing a far more precise figure:

   Date.now()         //  1337376068250
   performance.now()  //  20303.427000007
   

The high resolution timer is currently available in Chrome as window.performance.webkitNow(), and this value is generally equal to the new argument value passed into the rAF callback. Once the spec progresses through standards further, the method will drop the prefix and be available through performance.now().

You'll also notice the two above values are many orders of magnitude different. performance.now() is a measurement of floating point milliseconds since that particular page started to load (the performance.navigationStart to be specific).

In use

The key issue that crops is animation libraries that use this design pattern:

   function MyAnimation(duration) {
      this.startTime = Date.now();
      this.duration = duration;
      requestAnimFrame(this.tick.bind(this));
   }
   MyAnimation.prototype.tick = function(time) {
      var now = Date.now();
      if (time > now) {
        this.dispatchEvent("ended");
        return;
      }
       ...
     requestAnimFrame(this.tick.bind(this));
   }
   

An edit to fix this is pretty easy... augment the startTime and now to use window.performance.now().

   this.startTime = window.performance.now ?
                    (performance.now() + performance.timing.navigationStart) : 
                    Date.now();
   

This is a fairly naive implementation, it doesn't use a prefixed now() method and also assumes Date.now() support, which isn't in IE8.

Feature detection

If you're not using the pattern above and just want to identify which sort of callback value you're getting you can use this technique:

   requestAnimationFrame(function(timestamp){

if (timestamp < 1e12){ // .. high resolution timer } else { // integer milliseconds since unix epoch }

// ...

Checking if (timestamp < 1e12) is a quick duck test to see how big of a number we're dealing with. Technically it could false positive but only if a webpage is open continuously for 30 years. But we're not able to test if it's a floating point number (rather than floored to an integer). Ask for enough high resolution timers and you're bound to get integer values at some point.


We plan on pushing this change out in Chrome 21, so if you're already taking advantage of this callback parameter, be sure to update your code!

Websocket Frame Inspection now in Chrome DevTools

By Paul Irish at

While before we could see sockets being established, we haven't had inspection ability into the data going over the wire in websockets. Thanks to a WebKit patch from RIM, we can now see the frame data, along with small unicode arrows indicating which direction the data is going.

Open up your Chrome Canary or a fresh Chromium build for the latest changes here.

datalist landed in Chrome Canary

By Eiji Kitamura at

Filling out forms sometimes feel like cumbersome thing. Giving users multiple choice yet enabling them to type freely is important. The datalist element (which just landed on Chrome Canary (M20) makes this a breeze.

By using datalist, your app can define a list of suggested results users should select from. They can either select an option from the list or enter freeform text.

Live demo:
http://demo.agektmr.com/datalist/

Options can be paired with a datalist by specifying its id in an input element’s list attribute:

<input type="text" value="" list="fruits" />
<datalist id="fruits">
  <option value="Apple"></option> 
  <option value="Orange"></option> 
  <option value="Peach"></option> 
</datalist>

datalist is widely available on latest Firefox, Opera and Internet Explorer after version 10. So you don’t have to worry about compatibility too much, but if you want to make sure it works across browsers, try the following:

<datalist id="fruits">
  Pick your favorite fruit
  <select name="fruit_sel">
  <option value="Apple">Apple</option> 
  <option value="Orange">Orange</option> 
  <option value="Peach">Peach</option> 
  </select>
  or type one.
</datalist>
<input type="text" name="fruit" value="" list="fruits" />

If datalist is available on your browser, everything under the datalist except the option elements will be hidden. If you use this fallback mechanism, make sure your server catches both “fruit_sel” and “fruit” as query parameters.

Processing XHR2 file uploads in PHP

By Eric Bidelman at

My article "New Tricks in XMLHttpRequest2" has many fine examples, but what it doesn't have is any server code to illustrate how to handle files. If you're curious how to process a file upload using xhr.send(FormData), here's a quick example of an image upload in PHP.

This server is trivial but it demonstrates two things. The first is sending a file and extra payload at the same time. The second is how to grab the file (and other data) in PHP. Lastly, the image is encoded into a data: URL and included in a JSON response sent back to the client.

WebRTC Protothon

By Ilmari Heikkinen at

On March 24th, Google hosted the world’s first WebRTC developer event, the WebRTC Protothon. The hackathon brought together developers and designers from around the world, with browser engineers at hand to give assistance when needed.

For more details, check out the WebRTC Google+ post about the event. There is also a summary document with great photos.

Check out the demos in action either through a video or see the live demos below:

Puzzlible!

We blend!

Team charades

Ping Pong

Big boost to DOM performance - WebKit's innerHTML is 240% faster

By Sam Dutton at

We're very happy to see that some common DOM operations have just skyrocketed in speed. The changes were at the WebKit level, boosting performance for both Safari (JavaScriptCore) and Chrome (V8).

Chrome Engineer Kentaro Hara made seven code optimisations within WebKit; below are the results, which show just how much faster JavaScript DOM access has become:

DOM performance boosts summary

Below, Kentaro Hara gives details on some of the patches he made. The links are to WebKit bugs with test cases, so you can try out the tests for yourself. The changes were made between WebKit r109829 and r111133: Chrome 17 does not include them; Chrome 19 does.

Improve performance of div.innerHTML and div.outerHTML by 2.4x (V8, JavaScriptCore)

Previous behavior in WebKit:

  1. Create a string for each tag.
  2. Append a created string to Vector<string>, parsing the DOM tree.
  3. After the parsing, allocate a string whose size is the sum of all strings in the Vector<string>.
  4. Concatenate all strings in Vector<string>, and return it as innerHTML.

New behavior in WebKit:

  1. Allocate one string, say S.
  2. Concatenate a string for each tag to S, incrementally parsing the DOM tree.
  3. Return S as innerHTML.

In a nutshell, instead of creating a lot of strings and then concatenating them, the patch creates one string and then simply append strings incrementally.

Improve performance of div.innerText and div.outerText in Chromium/Mac by 4x (V8/Mac)

The patch just changed the initial buffer size for creating innerText. Changing the initial buffer size from 2^16 to 2^15 improved Chromium/Mac performance by 4x. This difference depends on the underlying malloc system.

Improve performance of CSS property accesses in JavaScriptCore by 35%

(Note: This is a change for Safari, not for Chrome.)

A CSS property string (e.g. .fontWeight, .backgroundColor) is converted to an integer ID in WebKit. This conversion is heavy. The patch caches the conversion results in a map (i.e. a property string => an integer ID), so that the conversion won't be conducted multiple times.

How do the tests work?

They measure the time of property accesses. In case of innerHTML (the performance test in bugs.webkit.org/show_bug.cgi?id=81214), the test just measures the time to run the following code:

for (var i = 0; i < 1000000; i++)
    document.body.innerHTML;

The performance test uses a large body copied from the HTML spec.

Similarly, the CSS property-accesses test measures the time of the following code:

var spanStyle = span.style;
for (var i = 0; i < 1000000; i++) {
    spanStyle.invalidFontWeight;
    spanStyle.invalidColor;
    spanStyle.invalidBackgroundColor;
    spanStyle.invalidDisplay;
}

The good news is that Kentaro Hara believes more performance improvements will be possible for other important DOM attributes and methods.

Bring it on!

Kudos to Haraken and the rest of the team.

Round-up of Web Browser Internals Resources

By Paul Irish at

In many cases, we treat web browsers as a black box. But as we gain a better understanding of how they work, we not only recognize where to make smart optimizations but also we push them farther.

The links below capture most of the resources that explain the innerworkings of web browsers.

Thanks Codrops for the fanciness. Thank you Anthony Ricaud for the resources.

If you know of other browser internals posts to capture, link them in the comments!

Taking an Entire Page Offline using the HTML5 FileSystem API

By Eric Bidelman at

Let's face it, AppCache is annoying and has problems [1, 2, 3]. One big limitation is the fact that it's impossible to dynamically cache assets on demand. Essentially, this makes it an all or nothing thing when it comes to taking an app offline. Either everything in the manifest is cached up front, or nothing is cached.

The HTML5 FileSystem API becomes an attractive solution for AppCache's shortcomings. One can programmatically store files and folder hierarchies in the local (sandboxed) filesystem and subsequently add/update/remove individual resources as necessary. My colleague, Boris Smus, even wrote a nice library to manage this type of offline caching in the context of games. The same idea can be extrapolated to work with any type of web app.

crbug.com/89271 is an important fix for the FileSystem API which makes relative filesystem: URL paths work like a charm.

Let's say for example, I've saved index.html in the filesystem's root folder (fs.root), created an img folder, and saved "test.png" in it. The filesystem: URL for those two files would be filesystem:http://example.com/temporary/index.html and filesystem:http://example.com/temporary/img/test.png, respectively. Then, if I wanted to use "test.png" for an img.src, I needed to use its full absolute path: <img src="filesystem:http://example.com/temporary/img/test.png">. That meant rewriting all of the relative urls in index.html to point to corresponding file's filesystem: URL. Not cool! Now, with this bug fix, I can keep the relative path to the file (<img src="img/test.png">) as they will resolve correctly to a filesystem origin.

This feature makes it trivial to pull down a page and save all of its resources offline, while still preserving the exact same folder structure as the online version.

CSS layout gets smarter with calc()

By Alex Danilo at

Creating a nice CSS layout starts with assigning sizes for all the things being placed in a web application. One highly requested feature has always been the ability to specify sizes using a mixture of sizing units. For example, it’d be nice to be able to reserve 50% of an area plus a fixed amount of space, say 10px. Well you can do that right now using the calc() property. You can use this feature anywhere a length or number is used, so you can use it for positioning things, or in rgb() color values as well, so it has lots of great uses in a style sheet.

What you can do with calc()?

The calc() property can be used anywhere there’s a CSS length or number in your stylesheet.

It gives you two main features to make layout more flexible:

  1. Mixing percentages and absolute values.
  2. Mixing sizing units.

Mixing percentages with absolute units

Let’s take a look at an example of mixing percentages with absolute units. Say we’d like to allocate 50% of the available area less a fixed amount of pixels, then we could write it as so:

#foo {
  width: calc(50% - 100px); 
}
<div id=”foo”>Always 100 pixels less than half the available area</div>

If it had a background color of green it’d look like:

and if you shrunk the parent size, it would look like:

The nice thing here is we always know the right hand edge of the content will be 100px to the left of the middle of the containing area. Being able to combine different value types this way allows your web application to handle layout on different size devices with far greater control than before.

Mixing units

Another great thing is the ability to combine units with different measurements to get a resulting size. For example you could set sizes relative to the current font size by mixing 'em’ and 'px’ units.

#bar {
  height: calc(10em + 3px); 
}

You can find some great examples of combining values here and here.

Try it out

With calc() you can use +, -, * and / to add, subtract, multiply and divide values, allowing all sorts of possibilities. You can use calc() anywhere a CSS length or number can be used. We’re also working on adding calc() for angle and frequency properties soon. The calc() property for lengths is available now in Chrome 19 (Dev channel build) by use of the '-webkit-calc’ property, in Firefox since version 8 using the '-moz-calc’ property and in Internet Explorer since version 9 unprefixed. Let us know what you think by leaving a comment below.

Optimizing JavaScript

By Seth Ladd at

JavaScript is relatively fast, but it can always go faster. Read more about how to optimize your JavaScript for performance.

How to write low garbage real-time JavaScript from Scirra, the HTML5 game making tool.

Optimizing for V8 – Introduction is written by Florian Loitsch, engineer on Dart’s JavaScript generation.

Optimizing for V8 – Inling, Deoptimizations is part 2 in Florian’s series.

From Console to Chrome – HTML5 and JavaScript for game developers from Lilli Thompson, Chrome Games engineer.