Wednesday, November 26, 2008

Profiling GWT application performance

By Sumit Chandel, Google Web Toolkit Team

A couple weeks ago, I talked about On-demand widget creation in GWT, a technique you can use to improve the performance of your own GWT applications. What we detailed there was how to apply the technique and what benefits it yields, however we only briefly touched on when and where to apply the pattern.

Applying on-demand widget creation in your application requires a measured understanding of your GWT application's performance. Profiling your application is key to identifying performance hot spots that could be improved using the lazy load pattern or other performance tune-up techniques.

The two key data points to consider when profiling your application are slowdowns and memory usage. Here the term slowdown relates to how slow your application performs in terms of the JavaScript and DOM manipulations that are being processed to run the application. Obviously slowdowns are bad because they lead to sluggish user experiences and less users on your site. Memory usage is equally important as an application that leaks or consumes large amounts of memory is likely to slowdown or crash the user's browser, which also leads to users leaving your site, most likely preceded by profuse cursing.

In this post I wanted to share some tips you could use to profile your own GWT application to help plan your on-demand creation strategy or apply other performance improving code fixes.

Profiling application performance

One of the tools that I usually use to profile GWT applications is the FireBug plugin for Firefox. It has great support for profiling JavaScript performance, which you can use to help find hotspots in your code where certain widget creation calls are taking up too much time and would be better loaded on demand.

Don't try this out just yet! The GWT compiler takes care of optimizing and obfuscating the JavaScript generated from your GWT source, therefore if you tried to run the FireBug profiler over your application without first compiling your application with the -style PRETTY flag, you'll have a really hard time figuring out what you're profiling.

To re-compile your GWT application in PRETTY mode, simply tweak the MyApplication-compile script if you used the applicationCreator or change your GWT compile run configuration to pass the -style PRETTY mode flag to the compiler (e.g. for Linux -compile script shown below):

#!/bin/sh APPDIR=`dirname $0`; java  -Xmx256M -cp  "$APPDIR/src:$APPDIR/bin:$APPDIR/../../gwt-user.jar:$APPDIR/../../gwt-dev-linux.jar"  com.google.gwt.dev.GWTCompiler -style PRETTY -out "$APPDIR/www" "$@"  com.google.gwt.sample.mail.Mail;

Once you've compiled in PRETTY mode, you should be able to use FireBug's JavaScript performance profiler with ease to help identify spots where you would want to load your widgets on demand rather than all at once. You can look forward to something like the screenshot below:

Screenshot showing how to use FireBug to profile your GWT application

Yet another way to profile your application is to do it manually by setting start / finish timestamps before and after the component you care about profiling, respectively. For example, let's say I wanted to determine the initial load time for the phone book application we developed as an example in the last blog post. I would first set a timestamp in my host HTML page, way up in the <head> of the document to make sure that the timestamp is recorded right when the first resource is picked up.

<title>Phonebook</title> <script language="javascript">   window.startTime = new Date().getTime(); </script> <iframe src="javascript:''" id="__gwt_historyFrame"  style="border: 0pt none ; position: absolute; width: 0pt; height: 0pt;"></iframe>

Then I would add the finish timestamp right at the end of the onModuleLoad() method, which should allow me to get a good indication of how long it took to load the application from start to finish.

 public void onModuleLoad() { ... displayLoadTime(); }  private native void displayLoadTime() /*-{ $wnd.alert("Load time: " + (new Date().getTime() - $wnd.startTime)); }-*/;

A note about what's being measured here - there are some elements that are not included in this measuring technique that affect load time performance. For example, any external scripts that are required to load your application will not be factored into this measure by default; nor will any references to other external resources such as stylesheets. You can include these resources in your load time measurement by adding the corresponding tag in your module XML file so that they are loaded synchronously. Also, image fetches are not included in this load time measure (although you can use the ImageBundle to gather your images in a single download that you can time individually). What's more, any code that is executed in a DeferredCommand or an IncrementalCommand will not be picked up with this measuring technique.

Also, this measure captures the time it takes to execute code to load and display the widget, but not actually render it on the browser DOM with styles applied. Capturing that kind of measure would require far from trivial browser instrumentation.

That said, this measuring technique is still a good way to profile parts of your application and compare them to other implementations since you can accurately measure the time it takes to execute the code responsible for loading your widgets. You could set up the same load time measurement around any other widget creation method that you want to evaluate for on-demand loading. If you feel that setting up alerts to display the load time measurements is a little silly, you may want to take a look at Fred Sauer's gwt-log project, which allows you to log timestamps among other things while developing your GWT application.

Another note about manual timer measurements - there is a slight difference in timer resolution depending in which browser you're running the code above. However, the delta between browsers is usually less than 15ms, and not a humanly noticeable delay. Therefore this difference should be negligible as you collect data points to plan out your on-demand widget creation strategy.

Another thing to keep in mind is that aside from timer resolution differences, browsers do have different load times in general, so it's important to profile your application for each major browser you intend on supporting for your users.

Aside from the profiling techniques described above, there is always the old fashioned way of doing things - just trying it out and seeing how it feels. When something feels sluggish, chances are that it is and needs to be fixed. If you want to drill down to numbers, typically a delay greater than 0.8 seconds in load time is perceived by the user as a full second delay, and starts to qualify an application as sluggish.

Profile and proceed

Hopefully this post gave you some guidance on how to go about collecting data points about your application in order to plan strategies and fixes to improve performance. While some of the profiling techniques listed above should go a long way, the state of profiling tools around Ajax is still evolving and will take some time before becoming the rich environment developers may remember from days of old (desktop development).

A good place to get more tips about profiling and performance tune up techniques is on our very own GWT developer forum. We have tons of developers posting up there who have developed their own tricks to profile their GWT applications and improve performance, and they'd be happy to share their insights if you're looking for more ways to improve your own applications.

[NFGB] Link - from Google Web Toolkit Blog
Related From Google Blogs:
Adding some style to the wiki on Google Code
Seminars for Success, Now for Website Optimizer
Display ad builder best practices
Getting Answers -- Fast

No comments: