Friday, June 15th, 2007

Safari 3: Onload firing, and bad timing

Category: Articles, Performance, WebKit

Mark Wilton-Jones has written up a detailed article on the behaviour and speed of Safari 3 in which he dives into how Safari fires onload at a different time than most other browsers, and other implementation details that mean that you can’t trust JavaScript in the page to do any benchmarking.

In Safari, it seems onload fires before the page has been displayed, before layout has been calculated, before any costly reflows have taken place. It fires before images have completed loading (this can also happen in rare cases in Opera, but Safari seems to do it everywhere), meaning that a substantial part of the load time is not included. So basically, onload is not trustworthy in Safari for checking page loading times.

It is possible to force Safari to layout the page before checking for the time. To do this, check for the offset values of any element, such as the offsetWidth of the body:

window.onload = function () {
var ignoreMe = document.body.offsetWidth;
var endTime = new Date();

Note, however, that this still does not include actually displaying the page, only calculating what will be displayed, so it is not perfect, but it does make it slightly closer to the behaviour of other browsers.

Mark finishes up talking about how to better benchmark the performance, and concluding that this doesn’t mean Safari is slow (it is clearly far from it), but it may not be as fast as it claims on TV :)

Posted by Dion Almaer at 10:03 am

3.5 rating from 55 votes


Comments feed TrackBack URI

I’ve run into a version of this on Safari 2, where standard DOM objects such as window weren’t available yet. I had to put a catch in and the set a timeout to try again. Safari 3 does seem to cause even more problems.

Comment by Mike — June 15, 2007

Yes I have run into this problem on rare occasions in safari 2 as well. The onload event defiantly triggers at a different time then most browsers. But it should be noted that this problem does not present itself very often and in most cases no adjustments are necessary.

Comment by evan108108 — June 15, 2007

Why even adopt to it?
Cant we expect some basic features from browsers?
It’s a beta, and developers should push for it to ‘grow up’ instead.
I kinda like Safari, but I dont see why we should make excuses for it.

Comment by mikael bergkvist — June 16, 2007

I try to safari 3 for windows. It crashes all the time.


Comment by Charlie Cheng — June 17, 2007

I agree with Evan. If it was found this fast, please post a bug at the apple website for Safari and they will more than likely fix the issue before we have to worry about it as developers :)

Comment by Chad — June 17, 2007

With respect, Mark is actually wrong on several points.

Yes, onload does fire earlier in Safari than in other browsers. However it does not fire until all resources have been loaded. We do delay doing the first layout (if the page loaded quickly enough) until after the onload fires. This is simply common sense, since to do otherwise is to waste time doing relayouts as a result of the changes that would be executed by a typical onload handler.

Note that Firefox does not defer its first layout until after onload, but – like Safari – it also defers painting until after the onload has fired. Neither browser will paint until after the onload if the page loads quickly enough. (I ought to know. I implemented this in Firefox.)

Regarding images, Safari does wait until the image data has been fetched before firing onload, but it does not decode images until they actually paint. Again this is common sense to keep memory usage down (and is especially useful on mobile devices). Most other browsers are not very smart in this respect and aggressively decode images before firing the onload. This is neither necessary nor required to be compliant with onload (and it wastes memory and hurts performance).

Finally, regarding the ibench test itself, ibench is specifically designed to work around onload. It forces the page to lay out and scroll, causing every browser in the test to paint each page twice. It also measures the overall time of the entire run, thus ensuring that as long as your paints take longer than the timeout values used, even the paints will be incorporated into the time. It’s actually really clever.

Comment by Dave Hyatt — June 20, 2007

Thanks Dave, I have corrected the statement about images loading to be decoding instead.

Now your point about iBench (I didn’t mention that in the original article, but since you have mentioned it I added it) – that just means you are penalising other browsers to make up for an unexpected behaviour in Safari, since scrolling can take a long time on some pages when layout was otherwise fast – opacity and fixed backgrounds in Opera come to mind here. It also means you are no longer testing just load&display times, so iBench does not represent what it is supposed to represent.

Sorry, but that is a cludge, not accuracy.

Your comments about when onload fires are valid (yes, it’s good for efficiency in some cases), but that does not contradict anything I have said about benchmark testing. The article was about benchmarking, after all.

Comment by TarquinWJ — June 25, 2007

All you have to do is add document.body.offsetLeft, and you’ll force Safari to do a layout (and get results that are comparable to Firefox). The differences really just boil down to lazy layout and lazy image decoding.

Comment by Dave Hyatt — June 27, 2007

“that just means you are penalising other browsers to make up for an unexpected behaviour in Safari, since scrolling can take a long time on some pages when layout was otherwise fast.”

Keep in mind that iBench is a third-party benchmark suite originally developed by Ziff Davis Media. It was under development before Safari even existed, so to say that the benchmark is designed to penalise other browsers due to a quirk in Safari’s behaviour is quite far-fetched. The design of the benchmark is to ensure that what is being timed is consistent across browsers.

Comment by Mark Rowe — July 2, 2007

The scrolling forced by the iBench isn’t really related to the layout delay either, it’s there to force painting (which I believe all browsers can defer until after onload and in some cases will skip entirely on a fast benchmark). Yes, it does overweight painting as a result (since you paint twice), but I don’t think this hurts other browsers more than Safari.

Comment by Maciej Stachowiak — July 3, 2007

Webkit doesn’t seem to wait for much of anything before firing onLoad according to this open bug report:

That seems to contradict somewhat with what Dave Hyatt states above (though obviously not much detail in the report), and sounds as if it would actually skew results…

Comment by Ian — July 6, 2007

Why Safari 3 causes mor eproblem?

Comment by 000 — July 10, 2007

I have had problems with a website that uses iframes to display dynamic content not loading properly in safari. Initial load is triggered by the following:

navigation is an iframe and blocknav gets the content from the database and does its own onload in its body tag to load the content iframes.

Would the issue in this discussion be the reason for the problem? If so, is there a workaround?

Comment by Penny — November 26, 2007

Sorry, it stripped my bit of code – here it is minus special characters and quotes

body, navigation)

Comment by Penny — November 26, 2007

Leave a comment

You must be logged in to post a comment.