In a recent blog entry, “The Hardware of Tomorrow Versus the Platform of Tomorrow”, Joe Walker raised some important Ajax issues. He talks about the increasing multiprocessing capabilities of today’s hardware, and web browsers’ inability to take full advantage of it.

He mixes two separate issues, talking about the lack of threading/concurrency support in the Javascript language, and also the lack of multi-threading within web browsers.
It’s this second issue that I want to explore here, particularly this comment:

“The problem is that web-browsers are a step backwards as far as multi-threading goes. In Javascript there is no such thing as a new thread, and worse than that, the entire platform (i.e. a browser) runs a single JavaScript thread. If a script in one window goes into a tight loop, or runs some synchronous Ajax then the browser HTML display freezes.”

Hmmm. That last sentence started gnawing at me. I’ll leave the “tight loop” problem for another day, but is it true that a synchronous XMLHttpRequest call will “freeze” the browser?

If Joe means that the page making the synchronous call freezes, I’ll agree. If it’s a synchronous, or blocking call, then nothing will happen within the page until it completes. We shouldn’t expect anything else. That’s what blocking I/O does.

But the earlier sentence implies that all browser windows (or tabs) will freeze during a sync call (“…the entire platform (i.e. a browser) runs a single JavaScript thread”). Is that true?

I wasn’t sure, but I knew how to find out.

A Simple Experiment

I wrote two programs. The first would run a single synchronous call to my web server. It calls a
tiny Perl server program that sends back a string like this:


Server: received at 21:19.14, replied at 21:19.17 (requested delay 3)

The server program accepts a single parameter, wait. The server program then waits the specifed number of seconds before replying. In the example above, the Ajax call
requested a 3 second delay.

The second program launches five asynchronous calls. They call the same server program. I can set each async call with a separate server delay time.

[This second program is described in more detail in an earlier blog entry here.]

For my experiment, I open up a browser window, then open a second browser window using the “New Window” menu option. This will (hopefully) assure that both windows are part of the
same browser process.

In window #1, I load my synchronous test and start a server request with a delay of 60 seconds. In window #2, I load the asynchronous test with each of the five tests set to three seconds.

The hypothesis is:

After launching the synchronous call, other browser windows or tabs will be frozen, and the asynchronous calls will not be serviced until the sync call completes.

Test Results

I tested with three different browsers on two different OSs. Here were my results:

Browser Sync Call Freezes Browser
Firefox 2.0.0.1 on Linux yes
Firefox 2.0.0.1 on Windows XP yes
Opera 9.10 on Linux no
MS Internet Explorer 6.0 on Windows XP no

For Internet Explorer and Opera, the results were essentially the same. Other windows/tabs did not freeze, and the asynchronous calls were all launched and completed while the
60 second synchronous call was still waiting for its server response.

The screenshot below shows the Opera test, with the synchronous test in the top window and the async test below. You can see that the sync request was received a second before the asyncs started, and that all the asyncs completed while the synchronous request was still pending.

sync-freeze.png

On Firefox, all browser windows ceased responding to any events until the synchronous call completed.

For IE and Opera, this means that each browser window’s Javascript has some degree of independence from other windows. A synchronous call in one window won’t block another window’s processing.

Unfortunately, if you’re writing web apps that act consistently across all the major browsers, this means you’ll need to assume the browser will freeze on synchronous calls. So in that sense, Joe is correct.

I haven’t looked at the underlying Firefox code, so I don’t know how hard this problem will be for them to remedy. But Opera and IE seem to have tackled it successfully.