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.
It’s this second issue that I want to explore here, particularly this comment:
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.
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.
I tested with three different browsers on two different OSs. Here were my results:
|Browser||Sync Call Freezes Browser|
|Firefox 22.214.171.124 on Linux||yes|
|Firefox 126.96.36.199 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.
On Firefox, all browser windows ceased responding to any events until the synchronous call completed.
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.