Jun 30

Web site performance is a very important topic. We should not let our end users wait for our sites and optimizing them for load time and rendering can save us thousands of dollars in traffic. There is a lot of great content out there on performance (spearheaded by Yahoo a few years back). When it comes to testing the performance after the page has loaded though there is a lot of things you can do wrong as you need to test things with timers and hope nothing else happening to your test machine interferes with your results.

The IE9 team wants to make it easier for developers and added a new Web Timing API in the browser. Web Timing is a W3C working draft and the API implemented the NavigationTiming part of the spec in window.msPerformance.timing and offers you a few sets of information without having to hack your own solution:

JAVASCRIPT:

interface MSPerformanceTiming{
     readonly attribute unsigned longlong navigationStart;
     readonly attribute unsigned longlong fetchStart;
     readonly attribute unsigned longlong unloadStart;
     readonly attribute unsigned longlong unloadEnd;
     readonly attribute unsigned longlong domainLookupStart;
     readonly attribute unsigned longlong domainLookupEnd;
     readonly attribute unsigned longlong connectStart;
     readonly attribute unsigned longlong connectEnd;
     readonly attribute unsigned longlong requestStart;
     readonly attribute unsigned longlong requestEnd;
     readonly attribute unsigned longlong responseStart;
     readonly attribute unsigned longlong responseEnd;
     readonly attribute unsigned longlong domLoading;
     readonly attribute unsigned longlong domInteractive;
     readonly attribute unsigned longlong domContentLoaded;
     readonly attribute unsigned longlong domComplete;
     readonly attribute unsigned longlong loadStart;
     readonly attribute unsigned longlong loadEnd;
     readonly attribute unsigned longlong firstPaint;
     readonly attribute unsigned longlong fullyLoaded;
}

You have even more granular control in timingMeasures

JAVASCRIPT:

interface MSPerformanceTimingMeasures{
     readonly attribute unsigned longlong navigation;
     readonly attribute unsigned longlong fetch;
     readonly attribute unsigned longlong unload;
     readonly attribute unsigned longlong domainLookup;
     readonly attribute unsigned longlong connect;
     readonly attribute unsigned longlong request;
     readonly attribute unsigned longlong response;
     readonly attribute unsigned longlong domLoading;
     readonly attribute unsigned longlong domInteractive;
     readonly attribute unsigned longlong domContentLoaded;
     readonly attribute unsigned longlong domComplete;
     readonly attribute unsigned longlong load;
     readonly attribute unsigned longlong firstPaint;
     readonly attribute unsigned longlong fullyLoaded;
}

Read the original post on MSDN and check out the demo on IE Test Drive

Continue reading »

Tagged with:
Jun 21

“A man’s got to do what a man’s got to do.” said the cowboy John Wayne. Mozilla’s new intern with the same name knows that Mozilla needs to do… and it needs to do performance. It isn’t just about JavaScript performance though, the battle for the hearts and minds is perceived performance. This is a tough game for Mozilla as the average user giving Chrome a shot is doing so on a fresh browser with no history, bookmarks, or add-ons. If you download a fresh Firefox nightly you may be surprised at how fast it is!

John has been doing some analysis comparing the perceived performance compared to Chrome:

and came up with some recommended actions for the team:

  • With just a few changes in the Firefox start-up process, we could greatly enhance the feeling of Firefox’s speed. The changes listed below are recommendations to help better the overall Firefox experience.
  • Draw the OS spinner icon as little as possible, but one solid break isn’t bad and might be better than one really long spinner.
  • Draw the browser chrome while the window is being animated (drawn) to size. So that most of the drawing happens simultaneously rather than sequentially.
  • Make a new ‘website loading’ icon with less visual weight that animates faster but is slightly larger (would allow a user to ‘see’ the faster animation).
  • ‘Lazy’ load tabs that are being restored (already being talked about).
  • Load upgrades and add-on updates upon browser close, not browser start.
  • Delay loading the website’s title until the website is ready for interaction.

Continue reading »

Tagged with:
Jun 10

Remember a time when you would make fun of Facebook for having such poor performance? You would see 400 scripts that would be loading, some of which that would have code for no reason. That was in the distant past now.

Makinde Adeagbo gave that great talk at JSConf about the copious amount of code they were able to delete while speeding up the site. With folks like him and Tom Occhino on the case, you know good things are happening.

If you do a view source on the Facebook home page these days, you see a lot of this:

HTML:

<script>big_pipe = new BigPipe(null, 4, null, true);</script>
<script>big_pipe.onPageletArrive({"id":"pagelet_intentional_stream","phase":1,"is_last":false,"append":false,"bootloadable":{"ufi-tracking-js":["F+B8D","CDYbm","A5j5z","3NVRu"],"UIIntentionalStreamRefresh":["F+B8D","CDYbm","EMOa3","zwScZ","fWhta","EzjZW"]},"css":["jFmkz","z9ULo","lShFv","bh3tE","1AZL5","OxGjK"],"js":["F+B8D","CDYbm","A5j5z","fWhta","uUXWA"],"resource_map":{"fWhta":{"name":"js\/a62kak05d08cgw8o.pkg.js","type":"js","permanent":false,"src":"http:\/\/static.ak.fbcdn.net\/rsrc.php\/z1AQ7\/hash\/qkma6pho.js"},"lShFv":{"name":"css\/sprite\/autogen\/e6h3iy.css","type":"css","permanent":false,"src":"http:\/\/static.ak.fbcdn.net\/rsrc.php\/zALI5\/hash\/cngu73tz.css"},"bh3tE":{"name":"css\/sprite\/autogen\/3jkv60.css","type":"css","permanent":false,"src":"http:\/\/static.ak.fbcdn.net\/rsrc.php\/z4M49\/hash\/7wet04gi.css"},"OxGjK":{"name":"css\/1b9p1ur0qpog8cgw.pkg.css","type":"css","permanent":true,"src":"http:\/\/static.ak.fbcdn.net\/rsrc.php\/zC6TL\/hash\/1quse983.css"},"3NVRu":{"name":"js\/ufi\/tracking.js","type":"js","permanent":false,"src":"http:\/\/static.ak.fbcdn.net\/rsrc.php\/z8CIM\/hash\/7c5lvnd6.js"},"EMOa3":{"name":"js\/lib\/util\/user_activity.js","type":"js","permanent":false,"src":"http:\/\/static.ak.fbcdn.net\/rsrc.php\/z2MJ2\/hash\/7q88hxyg.js"},"EzjZW":{"name":"js\/stream\/UIIntentionalStreamRefresh.js","type":"js","permanent":false,"src":"http:\/\/static.ak.fbcdn.net\/rsrc.php\/z7LZY\/hash\/5vjds43u.js"}},"requires":[],"provides":["pagelet_controller::home_intentional_stream"],"onload":["window.__UIControllerRegistry[\"c4c0ebcac26d1c478579b3\"] = new UIPagelet(\"c4c0ebcac26d1c478579b3\", \"\\\/pagelet\\\/home\\\/intentional_stream.php\", {\"is_multi_stream\":true,\"is_prefetch\":false,\"first_load\":null}, {});; ;","share_data={max_recipients:20}","window.__UIControllerRegistry[\"c4c0ebcac36a540af71b6d\"] = new UIIntentionalStream($(\"c4c0ebcac36a540af71b6d\"), \"nile\", 1276034077, 1276032692, 5, \"lf\", 10, 0, \"[]\", \"[]\", false, 300);;
//..
</script>
 

This is BigPipe, and it is explained by this Facebook Note:

To exploit the parallelism between web server and browser, BigPipe first breaks web pages into multiple chunks called pagelets. Just as a pipelining microprocessor divides an instruction’s life cycle into multiple stages (such as “instruction fetch”, “instruction decode”, “execution”, “register write back” etc.), BigPipe breaks the page generation process into several stages:

  1. Request parsing: web server parses and sanity checks the HTTP request.
  2. Data fetching: web server fetches data from storage tier.
  3. Markup generation: web server generates HTML markup for the response.
  4. Network transport: the response is transferred from web server to browser.
  5. CSS downloading: browser downloads CSS required by the page.
  6. DOM tree construction and CSS styling: browser constructs DOM tree of the document, and then applies CSS rules on it.
  7. JavaScript downloading: browser downloads JavaScript resources referenced by the page.
  8. JavaScript execution: browser executes JavaScript code of the page.

The first three stages are executed by the web server, and the last four stages are executed by the browser. Each pagelet must go through all these stages sequentially, but BigPipe enables several pagelets to be executed simultaneously in different stages.

The picture above uses Facebook’s home page as an example to demonstrate how web pages are decomposed into pagelets. The home page consists of several pagelets: “composer pagelet”, “navigation pagelet”, “news feed pagelet”, “request box pagelet”, “ads pagelet”, “friend suggestion box” and “connection box”, etc. Each of them is independent of each. When the “navigation pagelet” is displayed to the user, the “news feed pagelet” can still be being generated at the server.

In BigPipe, the life cycle of a user request is the following: The browser sends an HTTP request to web server. After receiving the HTTP request and performing some sanity check on it, web server immediately sends back an unclosed HTML document that includes an HTML tag and the first part of the tag. The tag includes BigPipe’s JavaScript library to interpret pagelet responses to be received later. In the tag, there is a template that specifies the logical structure of page and the placeholders for pagelets.

Performance results

The graph below shows the performance data comparing the 75th percentile user perceived latency for seeing the most important content in a page (e.g. news feed is considered the most important content on Facebook home page) on traditional model and BigPipe. The data is collected by loading Facebook home page 50 times using browsers with cold browser cache. The graph shows that BigPipe reduces user perceived latency by half in most browsers.

Continue reading »

Tagged with:
Jun 07

Safari 5 got out of the gate a touch early as the PR team shot their new release out before anything else was out there:

“Safari continues to lead the pack in performance, innovation and standards support,” said Philip Schiller, Apple’s senior vice president of Worldwide Product Marketing. “Safari now runs on over 200 million devices worldwide and its open source WebKit engine runs on over 500 million devices.”

Safari Reader makes it easy to read single and multipage articles on the web by presenting them in a new, scrollable view without any additional content or clutter. When Safari 5 detects an article, users can click on the Reader icon in the Smart Address Field to display the entire article for clear, uninterrupted reading with options to enlarge, print or send via email.

Powered by the Nitro JavaScript engine, Safari 5 on the Mac runs JavaScript 30 percent faster than Safari 4, three percent faster than Chrome 5.0, and over twice as fast as Firefox 3.6.* Safari 5 loads new webpages faster using Domain Name System (DNS) prefetching, and improves the caching of previously viewed pages to return to them more quickly.

Safari 5 adds more than a dozen powerful HTML5 features that allow web developers to create media-rich experiences, including full screen playback and closed captions for HTML5 video. Other new HTML5 features in Safari 5 include HTML5 Geolocation, HTML5 sectioning elements, HTML5 draggable attribute, HTML5 forms validation, HTML5 Ruby, HTML5 AJAX History, EventSource and WebSocket.

The new, free Safari Developer Program allows developers to customize and enhance Safari 5 with extensions based on standard web technologies like HTML5, CSS3 and JavaScript. The Extension Builder, new in Safari 5, simplifies the development, installation and packaging of extensions. For enhanced security and stability, Safari Extensions are sandboxed, signed with a digital certificate from Apple and run solely in the browser.

Some great features in there. Let’s get into some details:

Performance

Sam Pullara quickly ran Sun Spider on Chrome 6.0.422.0 and Safari 5 and the result is very close to a dead heat:

Safari 5 Total:         279.2ms +/- 1.9%     | Chrome 6 Total:      274.6ms +/- 6.2%
-------------------------------------------- | --------------------------------------------
  3d:                    36.0ms +/- 2.4%     |   3d:                   43.6ms +/- 18.0%
    cube:                12.8ms +/- 4.3%     |     cube:               16.0ms +/- 11.0%
    morph:               10.6ms +/- 6.4%     |     morph:              14.6ms +/- 32.2%
    raytrace:            12.6ms +/- 5.4%     |     raytrace:           13.0ms +/- 11.7%
                                             |
  access:                32.2ms +/- 5.0%     |   access:               30.6ms +/- 11.0%
    binary-trees:         5.4ms +/- 12.6%    |     binary-trees:        1.4ms +/- 48.6%
    fannkuch:            12.8ms +/- 4.3%     |     fannkuch:           12.2ms +/- 4.6%
    nbody:                8.6ms +/- 7.9%     |     nbody:              13.8ms +/- 17.3%
    nsieve:               5.4ms +/- 20.6%    |     nsieve:              3.2ms +/- 17.4%
                                             |
  bitops:                17.6ms +/- 13.8%    |   bitops:               22.6ms +/- 6.3%
    3bit-bits-in-byte:    2.4ms +/- 28.4%    |     3bit-bits-in-byte:   1.6ms +/- 42.6%
    bits-in-byte:         5.2ms +/- 10.7%    |     bits-in-byte:        5.8ms +/- 9.6%
    bitwise-and:          4.0ms +/- 69.5%    |     bitwise-and:         7.0ms +/- 0.0%
    nsieve-bits:          6.0ms +/- 0.0%     |     nsieve-bits:         8.2ms +/- 6.8%
                                             |
  controlflow:            2.8ms +/- 19.9%    |   controlflow:           2.4ms +/- 28.4%
    recursive:            2.8ms +/- 19.9%    |     recursive:           2.4ms +/- 28.4%
                                             |
  crypto:                16.6ms +/- 4.1%     |   crypto:               19.0ms +/- 9.3%
    aes:                  9.6ms +/- 7.1%     |     aes:                 7.6ms +/- 14.6%
    md5:                  4.0ms +/- 0.0%     |     md5:                 5.6ms +/- 12.2%
    sha1:                 3.0ms +/- 0.0%     |     sha1:                5.8ms +/- 9.6%
                                             |
  date:                  34.6ms +/- 2.0%     |   date:                 28.2ms +/- 7.2%
    format-tofte:        20.0ms +/- 0.0%     |     format-tofte:       13.4ms +/- 8.3%
    format-xparb:        14.6ms +/- 4.7%     |     format-xparb:       14.8ms +/- 7.0%
                                             |
  math:                  26.2ms +/- 4.0%     |   math:                 29.4ms +/- 8.8%
    cordic:               7.6ms +/- 9.0%     |     cordic:              9.4ms +/- 25.8%
    partial-sums:        13.0ms +/- 0.0%     |     partial-sums:       15.2ms +/- 10.7%
    spectral-norm:        5.6ms +/- 12.2%    |     spectral-norm:       4.8ms +/- 11.6%
                                             |
  regexp:                12.8ms +/- 4.3%     |   regexp:               16.0ms +/- 0.0%
    dna:                 12.8ms +/- 4.3%     |     dna:                16.0ms +/- 0.0%
                                             |
  string:               100.4ms +/- 1.4%     |   string:               82.8ms +/- 2.0%
    base64:              11.6ms +/- 5.9%     |     base64:              6.6ms +/- 10.3%
    fasta:               14.0ms +/- 0.0%     |     fasta:              12.0ms +/- 0.0%
    tagcloud:            23.0ms +/- 0.0%     |     tagcloud:           23.8ms +/- 5.7%
    unpack-code:         35.2ms +/- 3.0%     |     unpack-code:        29.0ms +/- 0.0%
    validate-input:      16.6ms +/- 4.1%     |     validate-input:     11.4ms +/- 6.0%

Standards

Now, lets look at how they size up in BrowserScope:

Topic Chrome Safari
Security 12/13 10/13
Rich Text 129/149 129/149
Selectors API 99.3% 99.3%
Network 9/16 10/16
Acid3 100/100 99/100

Incredibly close. Not that it should be a shock, since both parties are using WebKit under the hood (although the JS engines are totally different, and many other differences!)

Extensions

Panic were up on stage showing off Code Notes, a nice example of extensions for Safari:

The Coda Notes extension is built entirely in JavaScript, HTML, and CSS; the extension bar is basically an HTML file, and the page-flip effect is accomplished using a CSS transform. We draw on a transparent canvas element injected over the target page. Live text editing is done by setting the contentEditable attribute on the body of the page, thus turning Safari into an editor.

Great to see the new extension mechanisms on the Web are all of the Web (Chrome, Safari, Jetpack). Very cool indeed.

Continue reading »

Tagged with:
Jun 04

Thomas has a great post today on how he took the lovely Every Time Zone HTML5 app for the iPad and went deep to make it perform smoothly to match its beauty.

He has documented what he did:

  • Canvas optimizations over images: Thomas found out that using -webkit-gradient produces images which slow down the rendering on the iPad itself. His optimization was to use a <canvas> and only repaint what was needed.
  • Avoid text-shadow & box-shadow: Great. but slow
  • Hardware-acceleration is quite new… and buggy (aside: he called out some new scripty2 hw accel demos coming maybe as soon as next week!)
  • touch events fire before click events (use element[supportsTouch ? 'ontouchmove' : 'onmousemove'] = function(){})
  • Avoid opacity: Found that it can interfere with hw acceleration
  • Don’t use a js lib unless you need it. Every bit matters

Maybe iPhone OS 4 will change the characteristics…. but who knows. Good stuff.

Continue reading »

Tagged with:
May 05

At MIX, Microsoft showed that they are back in the browser game with a preview of IE9 “platform” (platform seems to mean ‘haven’t got it together as a real browser yet, but we wanted to get it to you guys ASAP’).

Today, they updated the preview as they said they would (claiming they will do new releases every 8 weeks or so).

Table stakes these days is performance. IE8 is so far behind, but the IE team is showing that with IE9 they will be strong contenders:

To go along with this, we haver the GPU story of hardware acceleration. Test drive some new demos such as this Flickr Explorer or the browser flip

There are other tools too:

The Developer Tools in IE9 Platform Preview 2 include new features. The Console window is now a full tab that includes diagnostic information from IE. Developers can use the “Change User Agent String” menu item to experiment with sending different that UA strings to sites with every request, selecting from preset strings or creating their own custom string. This complements another feature we’ve included – the new IE9 UA string. (Steve! Update BrowserScope! :)

This is good timing. Giorgio Sardo of Microsoft is on a browser panel that Ben and I are moderating at Web 2.0 Expo today. The panel has other heavy hitters: Douglas Crockford (Yahoo!), Brendan Eich (Mozilla), Charles McCathieNevile (Opera Software), and Alex Russell (Google). We are going to have some fun :)

Continue reading »

Tagged with:
Apr 18

steve_book_large

(Live blogging notes.)

At JSConf, Steve Souders walks us through several performance-optimising things on his mind lately.

Site Speed in PageRank

A week ago, Google announced site speed is going to be taken into account for PageRank. For Steve, this is a dream come true. Now companies are going to start investing in performance, so less of those slow-loading sites that frustrated him enough to get started down this performance path. One of the criticisms is that this will favour big companies, but Steve points out that smaller companies are often more nimble and able to adapt to changes like this.

As part of Google’s webmaster tools, site performance is shown to respective site masters, along with some guidance. Another good resource is http://www.webpagetest.org/. Other than its main measurement service, a great feature of WebPageTest is side-by-side comparisons. Show your manager a side-by-side against a competitor for guaranteed satisfaction.

Performance of Third Party Widget

There’s been something of a reversal in performance hotspots. Five years ago, it was the core web apps that were mostly slowing things down, much as teams would like to blame performance problem on 3rd party ads. Nowadays, those apps have been more finely tuned, and at the same time, people are using more 3rd party stuff – not just ads, but embedded widgets. All of which explains why Steve’s been looking at third-party widgets lately. You can see what he’s been up to at P3PC, a benchmark tool for third-party widgets.

A key question is how are the widgets embedded? People are no longer just doing the blocking document.write calls. Instead, it’s much more common to dynamically create a script tag and append to the page. But where and how do you append it? jQuery’s library code, for example, does it in a simple, elegant, manner:

JAVASCRIPT:

  1.  
  2. var head = document.getElementsByTagName(“head”)[0] || document.documentElement,
  3.   script = document.createElement(“script”);
  4. head.insertBefore(script, head.firstChild)
  5.  

Others, not so much. See Steve’s recent blog posts for more analysis on these techniques (e.g. on Google Analytics).

Frag Tag

An early proposal from Steve and Alex Russell …

<FRAG>
<script src="snippet.js"></script>
</FRAG>

The idea is that the frag loads independently; even document.write doesn’t block. And it could go further, into a sandboxing mechanism. “If we had this frag tag, it would be one of the biggest things website owners could do to improve the performance of their pages.”

Browser Disk Cache

The main message here is that browser disk cache is too small, and he’s been talking to vendors about upping capacity. And there’s a survey for you.

What makes sites feel slow?

So lately Steve’s been going back to basics and looking at user perception, thinking not just about how fast the Javascript takes to load, but how fast till the user sees anything. So he’s promoting the standard progressive enhancement pattern, similar to Facebook’s earlier talk:

* Deliver HTML
* Defer JS
* Avoid DOM
* Decorate later.

He’s done a couple of studies to this end:

* Charting page load time – as the user actually sees it – against market share…in an attempt to show faster sites mean bigger market share.
* Looking at initiail payload versus execution. Many of the sample (highly popular) sites are serving many functions on initial payload, which could be deferred until later – putting scripts at the bottom of the page, and loading scripts asynchronously.

Other Stuff

Check out:

* Browserscope, “a community-driven project for profiling web browsers”.

* HTTP Archive Format (HAR). An industry standard for capturing Used in an increasing number of tools, e.g. NetExport plugin in Firebug.

* Velocity Conference, which Steve founded with O’Reilly. June 22-24, Santa Clara.

Continue reading »

Tagged with:
Mar 01

Would we all like Steve to sit down with us on our project and do a performance case study? Well, we may not get that, but we are getting to at least sit in on others.

Steve has kicked off his long awaited series that runs performance case studies on third party content. I have been talking to Steve about this for a couple of years, so it is great to see it. It is a sensitive topic as you never want to show up a team when you are just trying to help and educate.

First on the block? The Digg widget.

diggwidgetstats

Steve goes into detail and finds a lot of short comings. You could probably guess some of the bad actors. Mr. document.write() appears for example. We get the problems, and proposed solutions to the issue. Steve also tries to note what a user of third party content can do regardless of if the third party guys fix their issues (put in iframe!).

Here are the most important performance issues along with recommended solutions.

  1. 9 HTTP requests, 52 kB transferred over the wire, and 107 kB of JavaScript (uncompressed) is a lot of content for a single widget.

    Recommendations:

    • Concatenate these three scripts: JS_Libraries, widgetjsvars, and omnidiggthis. (eliminates 2 HTTP requests)
    • Run Page Speed’s “Defer loading JavaScript” feature and see how much of the JavaScript is not used. If it’s sizable, delete it. (This feature is currently broken in the latest version of Page Speed, but a fix is imminent.) (eliminates ?? kB)
    • Optimize the images – widget-logo.png and get-widget.png can both be reduced by ~3 kB. (eliminates ~6 kB)
    • Sprite widget-logo.png and shade-com.png. (eliminates 1 HTTP request)
  2. The widget’s scripts block the main page’s content from downloading. Looking at the waterfall chart, the main page includes the image “digg-waterfall.png” (row 10). Notice how this image doesn’t start downloading until after all the scripts for the Digg widget are received.
    Recommendations:

    • Instead of loading the scripts using document.write, load them without blocking other downloads. The scripts are already suffering from race condition behavior, as evidenced by this comment from widgetjsvars:
      1: if (!digg || !digg.$) setTimeout(function() { diggwb(obj); }, 200); //hack for IE not loading scripts that are included via document.write until it decides too

    So it probably isn’t too much work to avoid race conditions when making all the scripts load asynchronously.

  3. The widget’s stylesheet blocks the main page from rendering in IE.

    Recommendations:

    • Instead of loading the stylesheet using document.write, load it via JavaScript as described in 5d dynamic stylesheets.
  4. Four of the resources aren’t cached long enough.
    Recommendations:

    • Two scripts aren’t cacheable because they have an expiration date in the past. widgetjs is part of the snippet, so it can’t have a long expiration date, but something like an hour or a day would be better than a date in the past. widgetjsvars could have a far future expiration date since its URL is specified in widgetjs.
    • The three images are only cacheable for a day. They should have a far future expires header since the image filename can be change if it’s modified.
  5. There are approximately 30 inefficient CSS selectors. Because this stylesheet is part of the main page, the selectors will cause the overall page to render more slowly when these selectors are applied to the elements in the main page.
    Recommendations:

  6. Four of the resources have ETags which reduces their cacheability.

    Recommendations:

    • Configure the ETags for widget.css, widget-logo.png, get-widget.png, and shade-com.png.

This is just the first example. What else would you like to see Steve tackle?

Continue reading »

Tagged with:
Feb 26

The Opera team has released 10.50 for Mac and along with it some impressive performance numbers:

  • Stabilization Improvements: You will find that this build is much more stable than the pre-alpha build.
  • More polished user interface: The whole UI is more polished now. We’re still not done yet, and expect more polishes and improvements in the builds to come.
  • Opera Unite: Opera Unite now works with this release. You can browse through and download unite apps through the Unite Apps Repository.
  • HTML5 <video>: This beta now supports the html5 <video> tag.
  • Widgets as standlone apps: We’ve already talked about widgets as standalone apps, but this functionality was till now, only available in windows builds. Now even in this build of 10.50 beta for mac, you can use widgets as standalone apps. Check out this ODIN post by Patrick Lauke on standalone widgets for more information.
  • New Developer Tools Menu: You can go to ‘View->Developer Tools’ Menu to access common and usefull tools for developers, such as Opera Dragonfly, cache information, the error console, the source code of the page, and more.

Gregg Keizer talks about the performance side of things

According to tests run by Computerworld, Opera 10.5 was nearly 15% faster than Safari for Windows and almost 20% faster than Google’s Chrome, the previous No. 1 and No. 2 browsers. Opera’s preview was more than twice as fast as Mozilla’s Firefox 3.6, over eight times faster than Opera 10.10, and 10 times faster than Microsoft’s Internet Explorer 8 (IE8).

We tend to talk a lot about WebKit, Moz, and IE…. congrats to the Opera team on their impressive work.

Continue reading »

Tagged with:
Feb 22

Steve Souders has put together a browser performance wishlist that answers the question “What are the most important changes browsers could make to improve performance?”

He also notes a couple of new ideas that he is very much behind:

SPDY

SPDY is a proposal from Google for making three major improvements to HTTP: compressed headers, multiplexed requests, and prioritized responses. Initial studies showed 25 top sites were loaded 55% faster. Server and client implementations are available, and some other organizations and individuals have completed server and client implementations. The protocol draft has been published for review.

FRAG

The idea behind this “document fragment” tag is that it be used to wrap 3rd party content – ads, widgets, and analytics. 3rd party content can have a severe impact on the containing page’s performance due to additional HTTP requests, scripts that block rendering and downloads, and added DOM nodes. Many of these factors can be mitigated by putting the 3rd party content inside an iframe embedded in the top level HTML document. But iframes have constraints and drawbacks – they typically introduce another HTTP request for the iframe’s HTML document, not all 3rd party code snippets will work inside an iframe without changes (e.g., references to “document” in JavaScript might need to reference the parent document), and some snippets (expando ads, suggest) can’t float over the main page’s elements. Another path to mitigate these issues is to load the JavaScript asynchronously, but many of these widgets use document.write and so must be evaluated synchronously.

A compromise is to place 3rd party content in the top level HTML document wrapped in a FRAG block. This approach degrades nicely – older browsers would ignore the FRAG tag and handle these snippets the same way they do today. Newer browsers would parse the HTML in a separate document fragment. The FRAG content would not block the rendering of the top level document. Snippets containing document.write would work without blocking the top level document. This idea just started getting discussed in January 2010. Much more use case analysis and discussion is needed, culminating in a proposed specification. (Credit to Alex Russell for the idea and name.)

Continue reading »

Tagged with:
Feb 19

jQuery 1.4.2 has been released today and it comes with some performance bumps (aggressive ones according to Taskspeed). Benchmarks are challenging, and John even calls that out:

For example, we saw significant overall performance speed-ups in Taskspeed simply by optimizing the $(“body”) selector because it’s called hundreds of times within the tests. Additionally we saw large gains by optimizing .bind() and .unbind() by a fraction of a millisecond – an inconsequential amount – especially considering that any cases where you would bind hundreds of events you would likely want to use .live() or .delegate() instead.

There are some new APIs a bunch of them around ergonomics:

In this release we’ve added two new methods: .delegate() and .undelegate(). These methods serve as complements to the existing .live() and .die() methods in jQuery. They simplify the process of watching for specific events from a certain root within the document.

For example:

JAVASCRIPT:

  1.  
  2. $(“table”).delegate(“td”, “hover”, function(){
  3.         $(this).toggleClass(“hover”);
  4. });
  5.  

This is equivalent to the following code written using .live():

JAVASCRIPT:

  1.  
  2. $(“table”).each(function(){
  3.         $(“td”, this).live(“hover”, function(){
  4.                 $(this).toggleClass(“hover”);
  5.         });
  6. });
  7.  

Additionally, .live() is roughly equivalent to the following .delegate() code.

JAVASCRIPT:

  1.  
  2. $(document).delegate(“td”, “hover”, function(){
  3.         $(this).toggleClass(“hover”);
  4. });
  5.  

The jQuery team continues to really put the pedal to the metal.

Continue reading »

Tagged with:
Feb 10

AJAX (Asynchronous JavaScript and XML) is an approach to web programming that has been enjoying great popularity ever since it was used by Google for many of its applications, notably Google Suggest and Google Map. There has been a lot of discussion about a number of issues related to AJAX including:

* tools and techniques for implementing AJAX (e.g. Ruby on Rai ls, DWR, Prototype, Sajax,

* Ajax.net) [1,3]

* business case for using AJAX [2]

* usability of web appli cations using AJAX [5]

* optimizing network bandwidth uti lization using AJAX for application development[6]

Considering that one of the key drivers for the rapid adoption of AJAX has been its promise of superior performance, it is surprising that there has not been much discussion of AJAX-specific performance testing. When we studied this in some detai l, we found that AJAX applications indeed present some unique issues and challenges, which we discuss in this paper.

Continue reading »

Tagged with:
preload preload preload