SOS

Shane O'Sullivan's technical blog… really ties the room together

Archive for the ‘Technical’ Category

Edgeconf 2012 Web Performance Panel

Posted by Shane O'Sullivan on February 12, 2013

Edgeconf 2012 Web Performance Panel

I had a great time at Edgeconf, taking part in the Web Performance panel. We got to discuss many of the common issues that web developers face when building complex web apps, such as avoiding reflow, repaints and avoiding garbage collection.

The full video is available now HERE.

The slides are available here

All other panel videos are available HERE, or will be soon if not yet uploaded.

Posted in Technical | Tagged: , | Leave a Comment »

Click, change then animate: My self imposed rule for a fast & smooth UI

Posted by Shane O'Sullivan on October 14, 2012

A few months ago I joined the Ads Interfaces team at Facebook, after almost two years on the mobile team, and am very proud of being part of the group that shipped a full rewrite of the Ads Create Flow (http://www.facebook.com/ads/create) last week.  The application is highly complex, with many varying user interface elements, lots of data floating around, validations and so forth, so it made sense to write it 100% client side in JavaScript. 

In many ways it’s a standard MVC application with

  • declarative view definitions, so you can easily relate the code to what you see in the Web Inspector
  • well defined data models which can be observed for changes
  • bidirectional bindings between views and models to keep the UI in sync with the data.  That is, if a piece of data changes, the UI should just update itself.  Of course, it is also possible to add code in between any binding if some more complex processing is needed.  For example, when changing the top level objective (clicking one of the huge buttons), I wanted it to animate the change, so rather the transference of the data update is delayed.

My New Rule

One of the primary lessons I took away from this is that asynchronous data fetching is one of the leading causes of users feeling like a UI is “webby”.  That feeling where the interface suddenly, with a jerk, jumps around and changes size.

This is often caused by images loading, or by an API call returning, resulting in the UI being redrawn.

I decided on a new rule to apply to interfaces I work on:

The UI can change suddenly when the user interacts with it.  All other changes should be smooth.

What this means is if the user clicks a link or a button, it’s OK to immediately change the UI, since they can see the causation.  However if new data comes back, or a large image loads shifting the entire UI up or down, this should be smoothly animated. 

I’ve found that this both gives an interface a more polished feel, but also draws the users eye to important information.  In addition, if they were already reading something, trying to make a choice of what to click next, if that jumps even a couple of centimeters they have to start searching for it again – it may have gone below the bottom of the screen.  However if it smoothly moves there over 300ms, they continue without much interruption.

It’s important to not go overboard with this of course.  Don’t animate everything, as it’ll feel gratuitous.  I’ve found that sticking to animating only asynchronous operations leads to an application feeling both fast and professional.

Image

Some examples in the Ads Create Flow are the large image that loads for Sponsored Stories (the bottom picture), and the entire Ad preview that loads as a result of a data callback (under Right Hand Column Preview).

Image

One caveat is that on IE 8 & 9, you’re going to have a bad time.  I chose to not bother with janky timer based animation solutions, both in the interest of saving time, and from a healthy disdain for legacy browsers.  So, I advise to stick with CSS3 animations, and let the users of old browsers have a working but less attractive application. 

Posted in Facebook, HTML5, Internet Explorer, Javascript, Technical | Leave a Comment »

What Git branch was I working on again?

Posted by Shane O'Sullivan on June 16, 2012

A situation I often find myself is remembering what Git branch I was working a few hours ago.  Partially this is my own fault, since I tend to name Git branches after task IDs, e.g. “12345″, in order to easily find them, but also just my brain has limited space and can’t remember more than three things at any one time.

A useful command I’ve found (for the Mac and probably Linux) is the following

for k in `git branch|perl -pe s/^..//`;do echo -e `git show --pretty=format:"%Cgreen%ci %Cblue%cr%Creset" $k|head -n 1`\\t$k;done|sort -r

This prints out a list of your branches, and the length of time since you last checked them out.  It makes it really easy to find that unmemorable branch.

Of course, it’s easier if you put that command in a reusable function, e.g.

function listGitBranchesByMod() {
    for k in `git branch|perl -pe s/^..//`;do echo -e `git show --pretty=format:"%Cgreen%ci %Cblue%cr%Creset" $k|head -n 1`\\t$k;done|sort -r
}

inside some *.sh file on your PATH.

I found this somewhere on the web, and cannot find it again. If it was you, please let me know so I can link to the original. Oh, and thanks!

Posted in Technical | Tagged: , | Leave a Comment »

Caching Events in Mobile Safari is a bad idea

Posted by Shane O'Sullivan on May 3, 2012

A recent issue with JavaScript devlopment that I’ve come across on Mobile Safari (note: not desktop Safari) is that if you add an event listener to a DOM node and for whatever reason keep a reference to the Event object you receive, you’ll run into errors.

This is because the same Event object is reused,  with its properties being updated every time.  I presume this is to conserve memory on mobile devices, as it is both in short supply and causes too much garbage collection, the enemy of responsive UIs.

The simple solution is, rather than caching the Event object (a bad idea any as it prevents it being garbage collected on other platforms), take what information you need from it, such as touch coordinates, and cache those instead.

Posted in Javascript, Technical | Leave a Comment »

Dynamically change deviceDpi on iOS

Posted by Shane O'Sullivan on December 13, 2011

When Apple released the iPhone 4 with a retina display, they quadrupled the pixel density.  This caused problems for websites, as all their assets would now look tiny.  To solve this, Apple made it so that websites would keep the old low density rather than the retina display, and would allow sites to opt in to using the hi-res display.

This is done by adding a <meta> tag to the header, like

  <meta name=”viewport” content=”initial-scale=0.5,maximum-scale=0.5,user-scalable=no,width=device-width,height=device-height,target-densityDpi=device-dpi” />

Note the 0.5 for the scale values.  This resizes the screen to take advantage of the full retina display.  Pretty.  To use the low-res version, the scale parameters are 1.

However, if you’re writing a static HTML based web app, with no backend, you can’t go sniffing the user agent to figure out whether to set the scale to 0.5 or 1 before generating the page, so you’ll have to do it in JavaScript.

Code!!

Here’s a simple script to do that, from my colleagues on the JSGameBench project at Facebook.  To use this, first put the meta tag above into the <head> of your document, with scale values of 1.

  if (window == window.top) {
        var meta_viewport = document.querySelector &&
          document.querySelector(“meta[name=viewport]“);
        if (meta_viewport && window.devicePixelRatio >= 2 ) {
          meta_viewport.setAttribute(‘content’, ‘user-scalable=no, width=device-width, height=device-height, initial-scale=0.5, maximum-scale=0.5′);
        }
  }

The script looks for the meta tag, checks if you have a hi-res Apple display, and switches the device screen scale to use all the pixels, not just one in four.

One more thing…..

If your web app uses CSS like

html, body {
  width: 100%;
  height: 100%;
}

to fit the app to the screen dimensions, and inside perhaps you have some JS based scroller, then you’ll need two further lines.  The script then becomes

if (window == window.top) {
  var meta_viewport = document.querySelector &&

    document.querySelector(“meta[name=viewport]“);
  if (meta_viewport && window.devicePixelRatio >= 2 ) {
    meta_viewport.setAttribute(‘content’, ‘user-scalable=no, width=device-width, height=device-height, initial-scale=0.5, maximum-scale=0.5′);
    document.body.style.width = ’200%’;
    document.body.style.height = ’200%’;
  }
}:

Without these extra lines, the page will only occupy one quarter of the screen, rather than all of it.

Now you have an app that looks right on older iOS devices, but still uses the hi-res screen of the iPhone4 for really sharp fonts and more.

Finally

Make sure that when designing your borders and other screen elements to use multiples of two.  E.g. have your borders be 2px, not 3px, so that when the phone divides them by two it’ll look right.

Posted in Technical | Leave a Comment »

CSS Box Sizing makes me happy

Posted by Shane O'Sullivan on September 13, 2011

Quick note: For anyone fighting for years against the CSS box model, where the visible size of an element depends on the sum of it’s width, height AND padding, check out the box-sizing: border-box;. It does exactly what we need, where if you say


.myclass {
width: 100%;
padding: 10px;
}

then myclass will still take up 100% width of its container, instead of overflowing.

https://developer.mozilla.org/en/CSS/box-sizing

Posted in Technical | Leave a Comment »

Quick canvas effect prototyping

Posted by Shane O'Sullivan on March 7, 2011

I’m doing some playing around with image processing on HTML5 Canvas elements, and so I’ve hacked together a simple page for prototyping different algorithms. Check it out http://chofter.com/EffectPrototyping.

The code abstracts away most of the complexities of working with Canvas elements, and just lets you get down to what you need: your pixel manipulation algorithms.  It provides a number of test images and examples to get you started, so have fun!

Oh and yes, it’s pretty ugly :-)

Posted in Technical | Leave a Comment »

Palm and the Mobile Expressionists

Posted by Shane O'Sullivan on January 28, 2011

Palm/HP have a new advertising campaign aimed at getting app developers all excited, and I was very happy to be a part of it.  Here’s hoping it helps give webOS the kick it needs to show developers how simple and fun it is to develop for.

Posted in Technical | Leave a Comment »

Flickr Mundo for Palm webOS

Posted by Shane O'Sullivan on September 5, 2010

I am very happy to announce the release of Flickr Mundo, a fully featured Flickr app for Palm webOS devices.  It is packed full of pretty much everything that a Flickr addict could possibly want, including:

  • Photo upload and download, with multiple simultaneous supported for both.
  • Read & add comments to photos and photo sets
  • Add/remove favourites
  • Bulk editing, e.g. choose 6 photos and add tags to them all in one go, add/remove them from a set or group, add/remove person tags…. and much more.
  • A great browsing experience, jump from one user to another,  open photo sets, groups and galleries.  Swipe from photo to photo.
  • Auto rotated wallpapers.   All the functionality from my other app Flickr Addict is included in Flickr Mundo.  Automatically download images in the background based on many different criteria and change the phone wallpaper on a schedule chosen by you.  No more boring backgrounds!
  • Context sensitive ‘Just Type’ search.  Wherever you are in the app, either hit the search icon or just start typing to search Flickr.  If you’re looking at a user, you can choose to just search that user. If looking at a photo group, you can search just that group.
  • Group search, find a photo group.
  • Location based search.  Find photos near you using GPS, or search for photos close to anywhere else you name.
  • Fullscreen slideshows with an optional audio playlist for playing music while watching your photos.

and much, much more, all wrapped in a highly polished UI that maximises the space of a small screen to the best effect.

A special thank you goes out to Jake and all the guys on the Palm Pre group on Flickr who did huge amounts of user testing on the beta version of the app. They spotted many obscure bugs, and made many suggestions for features and tweaks, most of which have ended up in the app.  Without them Flickr Mundo wouldn’t be anywhere near as complete, functional and fun as it is.

Flickr Mundo will be submitted to the Palm App Catalog in the next 24 hours, and should be available to everyone as soon as Palm approves it!

Update: Flickr Mundo has now been submitted to the App Catalog

Posted in Ajax, Flickr, Flickr Addict, Flickr Mundo, Javascript, json, mobile, Palm, Technical, wallpaper, WebOS | 61 Comments »

Dojo gets a speed boost on IE6 and IE7

Posted by Shane O'Sullivan on August 28, 2010

My former employer, Cúram Software, was good enough to give me a couple of months to work on the performance issues that Dojo and it’s widget project Dijit have in horrible legacy browsers IE6 and IE7.  Some of the fruits of that labour have now been checked into the code base and will be included in Dojo 1.6, out in Q4 2010.

So what I/we learned from the exercise?

DynaTrace rocks!

To begin with, I can’t praise DynaTrace enough.  It’s a fantastic piece of profiling software that delves deep into Internet Explorer’s innards to find every little horrible Microsoft bug.  It can take a while to get used to, but that is just because it presents you with so much data, all of it useful, and anyone would have trouble finding a way to make it easily consumable.  Long story short, if you’re having performance issues with your site in IE, download DynaTrace.

Touching className makes IE cry

Pretty much every time you change the className property of a node, IE6 and IE7 reflow the page.  It doesn’t matter if the new value is the same as the old one, or whether or not the changed CSS class has any visual effect, IE will redraw the page, resulting in a lot of time being lost.

Dojo was changing className too often, for example in dojo.addClass, if the class being added was already present, it would still assign the changed value to className.  I put a fix for this into v1.5.  There were also many cases where Dojo would use a combination of dojo.removeClass and dojo.addClass to replace a class, which changed className twice instead of just once.  To fix this, I’ve added a new public api dojo.replaceClass, which only changes className once.

Dijit widgets often add CSS classes to the DOM nodes which they are creating after the nodes have been inserted into the document.  This is costly, and a large performance improvement can be gained by applying these classes earlier in the lifecycle, before inserting into the document.  Bill Keese (Dijit master) checked in the first of the fixes for this for the BorderContainer recently, and a strategy is being formulated for the many other widgets that can benefit from this.  This work should be completed for v1.6.

Risky but…..

A solution that we cannot use for Dojo, but which we found gave huge performance gains for my company’s application, was to figure out what CSS classes Dojo would apply to a node and write those classes out when generating the HTML.  For example, when creating a dijit.layout.BorderContainer, our HTML contains the CSS class dijitBorderContainer.  There is an inherent risk with this approach, as Dojo may change the CSS classes in a later release, but if you’re willing to accept the risk and the upgrade pain, you can get a nice performance boost this way.

Reading offsetLeft and offsetTop is costly

When your code reads the offsetLeft or offsetTop of a node, all pending changes to the DOM have to be performed first.  This can be very expensive – we saw a number of single operations taking over 500ms each!  Many Dijits were using the dojo.marginBox method to get the left, top, width and height properties of a node, when all they needed was the width and height.

To solve this, I introduced a new method, dojo._getMarginSize, a private method that just returns the width and height of a node.  This has resulted in huge gains in performance on IE6 & 7, especially when used with layout widgets like the BorderContainer.

Unexplained gaps in DynaTrace profiles

We hit a bit of a wall at one point when analysing the performance profiles, where there was a 1.5 second gap in the profile where it seemed like nothing was happening, but everything was paused with the CPU at 100%.

We eventually discovered that there is a horrible bug in IE7 where if you have a :hover style on something that is not an anchor tag, it causes the rendering engine to go crazy, get all confused, and push the CPU up to 100% for no reason at all.

The solution: don’t user :hover styles on anything other than <a> tags.  Ridiculous I know, but so is the IE7 rendering engine.

Give it a go!

So, the long and short of it is that Dojo/Dijit should now be a good bit snappier on IE6 and 7.  With our application we got the load time for a huge application down from 20 seconds to 5 seconds using these techniques, making IE7 far, far more usable.  Of course it just flies on any other browser, even IE8 which, all credit to MS for once, is far less buggy than the earlier incarnations.

So feel free to try out the Dojo nightlies, you should find them to be a good bit more responsive in IE6 and 7 than just a few days ago, and now that we have learned some important lessons, Dojo will be even faster for v1.6.

Posted in Ajax, dijit, Dojo, Javascript, open source, performance, Technical | 8 Comments »

 
Follow

Get every new post delivered to your Inbox.

Join 428 other followers

%d bloggers like this: