Site Network: Personal | Professional | Photography

Technical Blog

This blog will contain content related to Java, Seam, Security, my sites and projects, as well as other technical subjects I am interested in.

Comments and questions are welcome!

JavaScript Speeds

June 30th, 2009

The JavaScript engines of popular web browsers vary greatly in performance. The variance in performance is surprising.

Running this test: http://celtickane.com/labs/web-browser-javascript-benchmark/

On my laptop, here are my results (lower is better, your results my vary):

Safari 4: 128
Firefox 3.5: 233
Camino: 615
IE 7: 1181

IE 7 is almost 10 X slower than Safari 4. With more and more sites building rich interfaces and AJAX driven interaction this can be a serious issue. Recently I was working on a redesign of some category navigation pages. The new interface used AJAX loaded content and multiple tabs to display content. It worked great under Firefox, IE 6, IE 8, Safari 3, Safari 4, but was painfully slow under IE 7. Slow enough that in deference to the high number of customers still using IE 7, and the potential sales loss, we had to remove much of the rich interface.

Be sure to test your rich interfaces in IE 7 and pay attention to performance. Until people move off of IE 7, we are all somewhat hamstrung with regards to how much JavaScript and AJAX we can use on eCommerce sites.

One thing to keep in mind is to try to limit the number of AJAX requests. IE 7 (and many other browsers) limit concurrent requests to 2, meaning if you're loading 12 fragments via AJAX, it will take 6 full requests/response cycles, each one taking ~200-500 ms. That adds up very quickly. You can pull everything down in one large AJAX request, parse that response's DOM tree, and extract the pieces you need, but A) that's more JavaScript you're using, and B) at some point you're better off just loading a new page.

Another thing to consider is that while JavaScript and AJAX allow us to build better interfaces for our users, allowing them to be better served by our sites, it's often easy to get distracted by what you can do, and by buzzwords, and lose sight of what actually benefits your users and what doesn't.

Friends don't let friends use IE 7.

Hard Drive Fail

June 16th, 2009

The hard drive in my server failed in a nasty way. So things may be slightly broken for a few more days, while I fix up things one by one.

Lessons learned: while backing up your data stuff is important (/var/www, /opt, etc...) DON'T forget to back up things like /etc and the list of the installed apt packages.

So please, be patient.

Why I like jQuery (over Dojo)

June 8th, 2009

With the caveat that I'm not an expert with Dojo/Dojox/Dijit, I'm currently switching a site off of Dojo onto jQuery. I've used jQuery on a few other sites, but typically just simple effects type stuff. This site has a lot of AJAX driven stuff going on: AJAX catalog navigation where we replace about 12 elements on the page with AJAX loads of other URLs serving back fragments, dynamic tabs which hide themselves if the AJAX source URL returns certain stuff instead of other stuff, etc... I've been writing lots of this JavaScript based on the Dojo framework, as that's what was handed to me, so I've done a lot of on the job Dojo learning. I was able to get things to work, so that was good. However, now that we're transitioning off of Dojo and onto jQuery, I'm amazed at how much easier the jQuery framework makes things. Aside from being smaller, simpler, and easier to understand (for me at least) I'm able to do the things I want to do, much more easily.

*note: some of the examples might be bad Dojo coding (some mine, some inherited) or might be due to me missing the "best" way to do something, however with both Dojo and jQuery I'm mostly using their documentation and/or Googling for how to do something, so any failings in the Dojo implementation are related to the quality and clarity of the documentation and available related pages.*

For instance, the Dojo code that was handed off to AJAX load a page into a div looks like this:

	dojo.xhrGet( {
	    // The following URL must match that used to test the server.
	    url : url2,
	    handleAs : "text",
	    timeout : 5000, // Time in milliseconds

	    // The LOAD function will be called on a successful response.
	    load : function(response, ioArgs) {
		dojo.byId("brandsDiv").innerHTML = response;
		return response;
	    },

	    // The ERROR function will be called in an error case.
	    error : function(response, ioArgs) {
		console.error("HTTP status code: ", ioArgs.xhr.status);
		return response;
	    }
	});

That times 12 for the 12 divs we're updating via AJAX. With jQuery I'm replacing that block with:

$("#brandsDiv").load(url2);

Simpler, no?

Also, with Dijit tabs, there's no easy way to hide a tab and resurrect it later. You have to save off the panel into a JavaScript variable, and reinstate it from that variable later. See how I handled hiding Dijit Tabs/ContentPanes in a TabContainer.

With jQuery Tabs I just use the built-in disable and enable methods along with one line of CSS to solve the same problem. Much easier.

I'm also loving the looks of the new jQuery Tools library from the FlowPlayer folks. Hopefully I'll be using that library soon on a few projects.

Seam 2.x Web Development

June 2nd, 2009
Seam 2.x Web Development by David Salter

Seam 2.x Web Development by David Salter

Packt Publishing just sent me a copy of their new Seam book entitled Seam 2.x Web Development. Authored by David Salter, it seems to be a well laid out practical guide to building web apps with Seam 2. I've only skimmed it so far, but will be posting an in-depth review once I'm able to read through it.

It's great to have a book that covers the new features of Seam 2 and provides examples of common Web 2.0 requirements such as OpenID integration, AJAX/RIA interfaces, and multi-tabbed browsing support using conversation scoped components. Personally I'm interested in reading about the new(ish) Identity Manager API (which I haven't played with yet) and trying to add OpenID support for the application I am currently building.

You can read the second chapter online here: Chapter 2: Developing Seam Applications and let me know what you think of it!

MSSQL, jTDS, NVARCHAR and Slow Indexes

May 23rd, 2009
Mr. Slow

Mr. Slow by Vox

An application I've built is going into production soon. It's the first application I've been involved with which will be using MSSQL server in production, I have some learning about MSSQL to do. After some research, I ended up using the jDTS JDBC driver instead of the Microsoft JDBC driver (which is feature incomplete and has some serious open issues).

We recently began performance testing and saw some odd behavior. Initially the application was performing well. However after few runs of the stress test the performance went from good to awful. The main web service call went from 600 ms to 23,000 ms. The database server's CPU was pinned, and the app servers were barely loading, spending all their time waiting for the database server to return queries. Stranger still, my local instance (running against PostgreSQL) performed well with the same code and same stress tests. Luckily a smart MSSQL DBA was able to figure out why the database was burning so much CPU and responding so slowly.

One of the primary queries is against a table which has been growing. The select query is simple and had an indexed column in the WHERE clause. Even as the table grew to over a million rows, it should have been a very quick query. Unfortunately it was taking several seconds to complete. My local instance had over 30 million rows in the same table in PostgreSQL and the query was lightening fast. The DBA discovered that the query execution was converting the indexed varchar column into nvarchar values for comparison with the query parameter used in the WHERE clause which was inexplicably coming over as an nvarchar. This datatype mismatch between the column definition and the query parameter meant that MSSQL was doing a scan of the million+ record index instead of the almost instant seek it should have been doing.

It turns out that jTDS sends String parameters over as Unicode (nvarchar) by default. It's easily fixed by adding this property to your connection-url:

sendStringParametersAsUnicode=false

That immediately fixed the performance issues.

So, if you're using jTDS and are using indexed varchar columns in your queries, you should add the property above to avoid your indexes being wasted and your queries running slowly.