Well, what browser is really fastest?

Internet Explorer vs. Firefox vs. Safari vs. Opera

According to the February 2008 trends in Browser Statistics, that is the order of the web browsers in terms of their popularity, or at least, in terms of their market share.

IE 54.4% (IE6=30.7, IE7=22.0, IE5=1.7), Fx 36.5%, Safari 2.0%, and Opera 1.4% (may be ignoring mobile phones?).

And according to Thecounter.com and Wikipedia the popularity in Q4 2007 is

81.14% for Internet Explorer, 13.81% for Mozilla/Netscape, 3.21% for Safari, and 0.67% for Opera.

So let us evaluate these browsers on the the fastest known MD5 implementation and see how they perform in reality.

The test we are going to perform uses code that is unmodified since earlier than at least some time in 2003:

  curl -I http://www.myersdaily.org/joseph/javascript/md5.js
HTTP/1.1 200 OK
Date: Tue, 25 Mar 2008 15:04:50 GMT
Server: Apache
Last-Modified: Tue, 21 Oct 2003 21:17:07 GMT
ETag: "a17aec-1587-3ca38fc1efac0"
Accept-Ranges: bytes
Content-Length: 5511
Vary: Accept-Encoding
Content-Type: application/x-javascript

MD5 script behind the test

As you probably know, the claim that my implementation of the MD5 algorithm in md5.js is the fastest is supported by the original benchmark page, which I have updated from time to time with the results from new browsers. It has been defeated a few times in individual tests by MD5_hexhash by Masanao Izumo. I think that he wrote a great script, but in fact, it is inferior to mine by far, except on a few odd browsers like Netscape Communicator 4.77 / Mac OS 9.2.2 or Opera 6.02 / Mac OS 10.2.6 (on which the checksum failed for Masanao Izumo's script). Yet I consider his script to be my only competitor, as the popular script by Paul Johnston is confusing to use and always significantly slower.

As I wrote about in my quick, incomplete introduction to the MD5 algorithm, there is a need to Petition the ECMA to support binary access to ASCII, UTF-8, and UTF-16 strings within JavaScript; writing scripts which access these strings is exceptionally difficult under current specifications. If I had a chance to rewrite my script (it doesn't need to be rewritten unless new features in JavaScript come out which support direct access to string code values in an array, as I have proposed to the ECMAscript committee), I would definitely integrate some of the good ideas of Masanao Izumo's great code, even though there is almost nothing else that can actually be optimized further than my script, until JavaScript itself has been improved. (I think the only reason that his isn't equally as fast as mine is because he may be less familiar with how to take best advantage of the underlying pre-defined way that JavaScript engines have been optimized, and to benefit from it in his code's performance.)

I hold my script to such a high standard that any time any script achieved a higher score than my script's lowest score, I reported that my script had been beaten. The only script which could ever beat it, even once, with all the iterations I tried, was the script by M.I. However, in some situations his MD5 checksum fails, rendering his algorithm useless. Although it was defeated in a single individual test on Opera 7.50 (Mac OS 10.2.8), it has stood the test of time ever since being first written, and has never been beaten in a complete experiment.

I am certain that my script could be defeated if someone were to take more advantage of localized functional variables, like f = function() {}; and any new knowledge about the JavaScript engines since 2003. But this article is simply a comment about browser performance using the best and most established MD5 script, unchanged and error-free for over five years.

The 1K = 1024 B test!

Each browser will be exposed to a test which compute the MD5 digest for a string with approximately 1024 bytes. The goal is to have the browser tested for about two seconds. A longer period of time might result in a "Slow Script" warning which would completely invalidate the speed test results.

We will continue performing the same computation repeatedly, and terminate the iteration when about two seconds has passed. (On old computers perhaps not even one iteration can be finished in two seconds.)

Testing...
<script src="http://www.myersdaily.org/joseph/javascript/md5.js">
/* I do not believe in type="text/javascript", as
JavaScript is so intertwined with HTML that it 
is wrong to use a type. Other languages like
VisualBasic are "plugins" to HTML that need a
type to be specified either by the webserver
or in the HTML source. */
</script>
<script>
inc_htmlinclude_js =
'Psalms 2:1 Why do the heathen rage, and the people imagi'
+ 'ne a vain thing?\n  2 The kings of the earth set themsel'
+ 'ves, and the rulers take counsel together, against the L'
+ 'ORD, and against his anointed, saying,\n  3 Let us break'
+ ' their bands asunder, and cast away their cords from us.'
+ '\n  4 He that sitteth in the heavens shall laugh: the LO'
+ 'RD shall have them in derision.\n  5 Then shall he speak'
+ ' unto them in his wrath, and vex them in his sore disple'
+ 'asure.\n  6 Yet have I set my king upon my holy hill of '
+ 'Zion.\n  7 I will declare the decree: the LORD hath said'
+ ' unto me, Thou art my Son; this day have I begotten thee'
+ '.\n  8 Ask of me, and I shall give thee the heathen for '
+ 'thine inheritance, and the uttermost parts of the earth '
+ 'for thy possession.\n  9 Thou shalt break them with a ro'
+ 'd of iron; thou shalt dash them in pieces like a potter\''
+ 's vessel.\n  10 Be wise now therefore, O ye kings: be in'
+ 'structed, ye judges of the earth.\n  11 Serve the LORD w'
+ 'ith fear, and rejoice with trembling.\n  12 Kiss the Son'
+ ', lest he be angry, and ye perish from the way, when his'
+ ' wrath is kindled but a little. Blessed are all they tha'
+ 't put their trust in him.';
onload = function() {
l = 1;
t = [new Date()];
do {
s = md5(inc_htmlinclude_js);
t[l] = new Date();
} while (t[l++]-t[0] < 2000);
z = inc_htmlinclude_js.length;
del = [];
for (i=1; i<l; i++)
del[i-1] = t[i]-t[i-1];
d = document;
opener = d.opener;
d.write('<div id="rrrr">');
d.write('<p>Results for ', navigator.userAgent);
d.write('<pre>');
d.write('md5 = ', s, '</pre>');
n = del.length;
zn = z*n;
tt = t[t.length-1]-t[0];
d.write('<p>Total iterations: n = ', n,
'<br/>Total size: (', z, 'n) = ', zn, ' bytes',
'<br/>Total time: t = ', tt, ' milliseconds',
'<br/>Average speed: r = ', 1000*zn/tt, ' bytes/second.');
d.write('<p>Individual results in milliseconds:<p>', del.join(', '));
d.write('</div>');
opener.f.r.value = document.getElementById('rrrr').innerHTML;
}
</script>

Include a note about your computer if you wish:

The correct md5 value should be babc2d5c5c0ac1f4a7aee225f1bcb00a

After giving you the average speed in bytes/second, the speed test will also give you the individual results of each iteration. You can tell whether your browser has a little bit of trouble by seeing the values in the individual results are uniformly distributed or erratic. Also, some browsers may be slower at the beginning or the end of the iteration because they are still processing some other activities going on in the web page, like rendering the page at the beginning, etc.

Note that bad browsers are unable to accurately report times for individual iterations because the precision of their JavaScript clock/timer is not anywhere close to being measured in milliseconds.

Keep watching! Results will be posted soon!

The tests will be done on the same computer as each other, with each browser running alone and all other applications closed.

Results

Results for Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; InfoPath.1; .NET CLR 1.1.4322)

md5 = babc2d5c5c0ac1f4a7aee225f1bcb00a

Total iterations: n = 78
Total size: (1134n) = 88452 bytes
Total time: t = 2000 milliseconds
Average speed: r = 44226 bytes/second.

Individual results in milliseconds:

31, 32, 31, 15, 32, 31, 16, 31, 31, 16, 31, 31, 16, 31, 16, 31, 31, 16, 31, 31, 16, 31, 16, 31, 31, 16, 31, 31, 16, 31, 16, 31, 31, 16, 31, 32, 15, 31, 16, 31, 32, 15, 31, 32, 15, 32, 15, 31, 32, 15, 32, 31, 15, 32, 15, 32, 31, 15, 32, 31, 16, 31, 15, 32, 31, 16, 31, 31, 16, 31, 31, 16, 31, 16, 31, 31, 16, 31

¬e=3.0 GHz pentium 4, 1.00 GB ram

Results for Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1) Gecko/20061010 Firefox/2.0

md5 = babc2d5c5c0ac1f4a7aee225f1bcb00a

Total iterations: n = 124
Total size: (1134n) = 140616 bytes
Total time: t = 2000 milliseconds
Average speed: r = 70308 bytes/second.

Individual results in milliseconds:

16, 16, 15, 31, 16, 16, 15, 16, 31, 16, 15, 16, 16, 15, 32, 0, 15, 31, 16, 16, 15, 16, 16, 31, 0, 15, 16, 31, 16, 0, 16, 31, 15, 16, 16, 15, 16, 16, 15, 16, 15, 16, 16, 31, 0, 16, 15, 16, 31, 16, 0, 15, 16, 31, 16, 0, 15, 16, 31, 16, 16, 0, 15, 31 , 16, 16, 0, 15, 16, 31, 16, 15, 0, 16, 16, 31, 16, 0, 15, 16, 31, 16, 15, 0, 16, 16, 31, 15, 0, 16, 16, 15, 16, 31, 16, 0, 15, 16, 16, 15, 16, 16, 15, 16, 15, 16, 16, 15, 16, 16, 15, 16, 15, 0, 32, 15, 16, 16, 15, 0, 16, 15, 32, 15

Results for Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.13 (KHTML, like Gecko) Version/3.1 Safari/525.13

md5 = babc2d5c5c0ac1f4a7aee225f1bcb00a

Total iterations: n = 253
Total size: (1134n) = 286902 bytes
Total time: t = 2000 milliseconds
Average speed: r = 143451 bytes/second.

Individual results in milliseconds:

15, 16, 0, 16, 0, 15, 0, 16, 16, 0, 15, 0, 16, 0, 15, 0, 16, 0, 16, 0, 15, 0, 16, 0, 16, 0, 15, 0, 16, 0, 15, 0, 16, 0, 16, 0, 15, 0, 16, 0, 16, 0, 15, 0, 16, 0, 15, 0, 16, 0, 16, 0, 15, 0, 16, 0, 16, 0, 15, 0, 16, 0, 15, 0, 16, 0, 16, 0, 15, 0, 16, 0, 16, 0, 15, 0, 16, 0, 15, 0, 16, 0, 16, 0, 15, 0, 16, 0, 16, 0, 15, 0, 16, 0, 15, 0, 16, 0, 16, 0, 15, 0, 16, 0, 16, 0, 15, 0, 16, 0, 15, 0, 16, 0, 16, 0, 15, 0, 16, 0, 16, 0, 15, 0, 16, 0, 15, 0, 16, 0, 16, 0, 15, 0, 16, 0, 16, 0, 15, 0, 16, 0, 15, 0, 16, 0, 16, 0, 15, 0, 16, 0, 16, 0, 15, 0, 16, 0, 15, 0, 16, 0, 16, 0, 15, 0, 16, 0, 16, 0, 15, 0, 16, 0, 15, 0, 16, 0, 16, 0, 15, 0, 16, 0, 16, 0, 15, 0, 16, 0, 15, 0, 16, 0, 16, 0, 15, 0, 16, 0, 16, 0, 15, 0, 16, 0, 15, 0, 16, 0, 16, 0, 15, 0, 16, 0, 16, 0, 15, 0, 16, 0, 15, 0, 16, 0, 16, 0, 15, 0, 16, 0, 16, 0, 15, 0, 16, 0, 15, 0, 16, 0, 16, 0, 15, 0, 16, 0, 16, 0, 15, 0, 16

Results for Opera/9.26 (Windows NT 5.1; U; en)

md5 = babc2d5c5c0ac1f4a7aee225f1bcb00a

Total iterations: n = 136
Total size: (1134n) = 154224 bytes
Total time: t = 2000 milliseconds
Average speed: r = 77112 bytes/second.

Individual results in milliseconds:

16, 16, 15, 16, 15, 16, 16, 15, 16, 16, 15, 16, 15, 16, 16, 15, 16, 0, 16, 15, 16, 15, 16, 16, 15, 16, 16, 15, 16, 15, 16, 16, 15, 16, 0, 16, 15, 16, 15, 16, 16, 15, 16, 16, 15, 16, 15, 16, 16, 0, 15, 16, 16, 15, 16, 15, 16, 16, 15, 16, 16, 15, 16, 15, 16, 0, 31, 16, 16, 15, 16, 15, 16, 0, 16, 15, 16, 16, 15, 16, 15, 16, 16, 15, 16, 16, 15, 0, 16, 15, 16, 16, 15, 16, 16, 15, 16, 15, 16, 16, 15, 16, 16, 0, 15, 16, 15, 16, 16, 15, 16, 16, 15, 16, 15, 16, 16, 15, 16, 0, 16, 15, 16, 15, 16, 16, 15, 16, 16, 15, 16, 15, 16, 0, 16, 15

Conclusion

Let's assign a score of 100% to Internet Explorer. Then the scores are:

Internet Explorer 6.0 100%
Firefox 2.0.12 159%
Safari 3.1 324%
Opera 9.26 174%

Clearly the winner is Safari 3.1 with almost double the performance of all other browsers, more than double of both Firefox and Internet Explorer.

Update: 3-26-08. We have repeated the tests to see how browsers fare on a Core 2 Duo computer rather than a Pentium 4. Also, we have tested two new beta browsers.

Internet Explorer 7.0 57834 bytes/second = 100%
Firefox 2.0.12 118503 = 205%
Safari 3.1 221697 = 383%
Opera 9.26 100926 = 175%
Opera (3-18-08) 241542 = 418%
Firefox 3.0b4 298093 = 515%