Blog


Deep Tracing of Internet Explorer

After reading a recent post by Steve Souders concerning a free tool called dynaTrace Ajax, I was intrigued. It claimed to provide full tracing analysis of Internet Explorer 6-8 (including JavaScript, rendering, and network traffic). Giving it a try I was very impressed. I tested against a few web sites but got the most interesting results running against the JavaScript-heavy Gmail in Internet Explorer 8.

I typically don't write about most performance analysis tools because, frankly, most of them are quite bland and don't provide very interesting information or analysis. dynaTrace provides some information that I've never seen before - in any tool on any browser.

dynaTrace Ajax works by sticking low-level instrumentation into Internet Explorer when it launches, capturing any activity that occurs - and I mean virtually any activity that you can imagine. I noticed very little slow down when running the browser in tracing mode (although it's sometimes hard to tell, considering the browser). However all of the tracing is recorded and saved for later, making it easy to record sessions for later analysis.

dynaTrace Ajax

Above is the result of a recorded session, logging in to Gmail, reading a mail, and logging back out again. All aspects of the session are saved: Network requests, JavaScript source, all DOM events, etc. I had a hard time finding information that wasn't saved by the tool.

This is the full timeline view of loading a single the Gmail inbox. All network traffic, JavaScript parsing and execution, browser events, and CPU load can be seen.

You can select a segment of the timeline and get a view that looks like the following:

In the above you can see a clearer picture of the exact interactions happening. A phenomenal amount of inline JavaScript execution followed by page layout calculation coinciding with loading of some data over the network. You can mouse over the individual blocks on the timeline to get more information (such as if the JavaScript execute was the result of a timer or what Ajax requests were firing to cause the network traffic). Additionally you can click the blocks to dive in and take a deeper view of the trace.

Digging in to the execution of an XMLHttpRequest on a page we get to see some of the full execution stack trace - and this is where the tools starts to become really interesting. The tool is capable of tracing across JavaScript, through the native XMLHttpRequest, through the network request, and back to the handler that fires when the request is done. This is phenomenal. This is the first tool that I've seen that's capable of tracing through native methods to give you a picture of what activity triggers which actions and the complete ramifications of what happens (in both CPU usage and execution time).

Note that in the stack trace view you can click any piece of code and see its location anywhere inside the source code (and this even works after you've already closed the browser and have moved on - all source code is saved for later analysis).

While it's interesting to trace through code to look for problems the bigger question is usually: Where are slowdowns occurring? This is where the HotPath view comes into play:

This looks like a typical execution count view - like the one that you might see in Internet Explorer's built in tool or in Firebug - except for one important point: This view includes JavaScript parsing and layout rendering times. This is huge! No other tool provides information on how long it takes to parse all the JavaScript code on your site or how long it takes to do all the rendering. Clicking those entries allows you to see a breakdown of every time JavaScript was parsed or a layout was rendered - from which you can trace back to get even more information about what caused those actions. I don't want to seem too excited but I really am, this is just an incredible amount of information - and it gets even better:

Not only can you see the execution count for your defined JavaScript methods but you can also see execution time for the built-in DOM methods! Wondering what native method calls are slowing down your application? Wonder no more. From the HotSpot view you can filter by DOM or regular JavaScript and see exactly where execution time is going and what methods are so slow.

dynaTrace provides an additional view, called PurePath that attempts to figure out problematic scripts:

Just another way to try and get a full picture as to where your application is slowing down and what may be causing the problem.

In all I'm hugely impressed with this (free!) tool and am already using it to do more testing and performance analysis on my code. I don't think any browser has ever had a tool capable of this type of analysis, let alone Internet Explorer 6 and 7, which are still a very real part of any developer's workflow.

I chatted with some of the dynaTrace guys and asked them to add in memory profiling and to support more browsers. If they can provide this quality of instrumentation for CPU and execution time I hope they can do the same for memory usage, the next un-tapped realm of JavaScript performance analysis.

Tags: analysis, performance, tracing, ie, tools

JavaScript Engine Speeds

Recently, I've been spending a lot of time analyzing the speed of pure JavaScript engines, looking at how well they perform and what their particular strengths and weaknesses are. To start with, I analyzed the bleeding-edge code from:

Right now I'm only looking at pure, JavaScript-only, tests (no tests of DOM or other APIs) and am NOT looking at the speed of the browsers' native JavaScript engine implementations. (So, even though you may see a speed for a particular engine, that does not directly correlate to the speed of the JavaScript running within the browser itself. There's always a significant amount of overhead required to run JavaScript code seurely within a browser, thus the efficiency of that security layer will frequently become a deciding factor in the results.

The four engines that I picked all had complete JavaScript implementations and usable JavaScript shells (that way I could feed my tests in and have them cleanly run).

To browse the results I've pulled together a simple application that can be used to view a representation of the data from all the major JavaScript engines paired with the code from the tests which run them.

Right now the browser works fine in Firefox, is quirky in Opera and Safari, and explodes in IE (it requires canvas support). I'll finesse it into shape when I have a little more time this week.

Note: This demo uses a bunch of functionality from the new jQuery UI library, including themes, tabs, accordion, and resizables.

Tags: analysis, speed, data, javascript, ecmascript

Number of RSS Readers

A piece of information that I've been analyzing, in my spare time, is the number of readers on this web log. How this is done can be very tricky, as there are a number of factors (people can click your RSS feed and 'view' it in their browser, but it doesn't mean that they're reading it on a regular basis). Regardless, the easiest way to figure out, approximately, how many readers you have is to count the numbers provided by news aggregators in their user agent string. Some information on common user agent formats can be found in an excellent write up on InsideGoogle.

I've also pulled together some code, from a Perl application that I'm writing in my spare time, if you're interested in tracking something like this yourself.

my %rss = (
  "Blog" => ["/index.rdf","/?p=rss","/blog/index.rdf"],
  "Links" => ["/links/index.rdf"],
  "Projects" => ["/projects/index.rdf"]
);

my @rss_names = qw( users subscribers readers );
my %rss_count = ();
my %rss_ip = ();

sub rss {
  my ( $page, $user, $ip ) = @_;
  my $found = 1;

  foreach my $i ( keys %rss ) {
    foreach ( @{ $rss{ $i } } ) {
      if ( $page eq $_ ) {
        unless ( exists $rss_ip{ $i }{ $ip } ) {
          my $count = 1;
          foreach ( @rss_names ) {
            if ( $user =~ /(\d+) $_/i ) {
              $count = $1;
            } elsif ( $user =~ /$_ (\d+)/i ) {
              $count = $1;
            }
          }
          $rss_count{$i} += $count;
          $rss_ip{ $i }{ $ip } = 1;
        }
        return 0;
      }
    }
  }

  return 1;
}

In a nutshell, this is what the code is doing: Each RSS feed is analyzed, of which each feed can have multiple URLs. The URLs for the RSS feeds are specified in the first declaration:

my %rss = (
  "Blog" => ["/index.rdf","/?p=rss","/blog/index.rdf"],
  "Links" => ["/links/index.rdf"],
  "Projects" => ["/projects/index.rdf"]
);

(This pieces of code is what I use on my weblog.) I especially like the multiple URLs to RSS feed due to mis-behaving news aggregators not following updated permanent redirects. This way I can make sure that everyone reading the same content is pulled together.

The next aspect of RSS tracking lies in figuring out if the IP of the RSS user is unique, or not. Currently, this is the only way to track users who don't use some form of a public aggregator and only pull information using some form of a desktop news application.

The main subroutine, itself, accepts three arguments. $page takes the URI of the requested page (e.g. /index.html). $user takes the user's user agent string. $ip takes the user's IP. The best way to use this subroutine is by iterating over your web server access logs (whatever form they may be in), parsing out the three pieces of information described above, and feeding it into this method.

After you're done parsing all the requested information from your logs, you now have a nice little hash of information, that will look something like this:

%rss_count = (
  "Blog" => 155,
  "Links" => 31,
  "Projects" => 45
);

Unfortunately, you end up having to take this figures with a grain of salt, considering that users sometimes request a feed, but end up not becoming a regular subscriber. You'll probably notice that you're subscription numbers fluctuate on a day-by-day basis, this is mostly due to the fact that different numbers of people read on different days of the week (weekends are very slow reader days).

So, play around with this code, have some fun - I'm hoping to release a full stats app that I've developed (using the above code), here soon.

Tags: rss, blogs, news, aggregator, data, analysis, stats

JavaScript Books

Secrets of the JavaScript Ninja

JavaScript Secrets

Secret techniques of top JavaScript programmers.

Pro JavaScript Techniques

Pro JavaScript

The best techniques for professional JavaScript. Published by Apress.

Micro Updates

John Resig Twitter Updates

@jeresig

Infrequent, short, updates and links.

JavaScript Jobs



Hosting provided by: Ruby Hosting by Engine Yard