It seems like every month, Safari runs just a little bit slower on my PowerBook. Some sites are worse then others–I can’t visit or without staring at the spinning beachball of death for 5 or 10 seconds. Even worse, whenever this happens, Mail or NetNewsWire tend to go away as well, rendering my system effectively useless. Clearly something was eating a bunch of CPU time, but there was no obvious way to tell what it was.

So, this afternoon I decided that I’d bite the bullet and find the problem. I downloaded Apple’s CHUD toolset, installed it, and fired up Shark, Apple’s system-wide profiling tool. I left it running in the background, collecting performance data, while I loaded up a bunch of slow websites, and then took a look at the profile that it generated. The single biggest block of time was spent running CFStringFindWithOptions (9.1%). Drilling down a bit, it looks like most of those calls came from NSHTTPCookieDiskStorage (8.8% of the total). So I fired up Safari’s cookie editor and realized that I hadn’t cleared out my cookie cache since I first installed Safari–there were several thousand cookies sitting there. From looking at the profile, I’d guess that OS X’s cookie system does a linear search through the whole cookie jar every time it hits a page. Since the same basic code is used by every native OS X application, that’d explain why both Safari and NetNewsWire were slow.

I spent a few minutes cleaning out the cookie jar, and–amazingly enough–Safari’s a lot faster. I haven’t seen the beachball of death since I cleaned up the cookies; before I was seeing it every minute or so. I don’t have any hard benchmark numbers, but subjectively it feels a lot better.

So, if Safari’s running slow, try cleaning out your cookies.

Update: Thinking about it a bit more, it seems obvious what’s happening–every single HTTP request does a linear read of the cookie database. With some sites, a decent percentage of the HTTP requests also result in a write to the cookie database. Most likely, this triggers a reader-writer lock of the cookie DB, so the write stalls waiting for a bunch of slow reads, and then a handful of writes back up one after the other, so even if the cookie handling is only eating 9% of the CPU, the total wall-clock time lost due to locking could easily be really substantial. Even worse, this effectively serializes HTTP requests, limiting the system to one cookie-invoking request at a time. That’d explain a lot of the weird behavior that I’ve seen in Safari, where one slow website will block a dozen tabs from loading. Does anyone know if Tiger has a new cookie implementation? Any decent database system will solve all of these problems.

Tiger Update: It still uses ~/Library/Cookies/Cookies.plist–no SQLite. So it’s this is probably still a problem with Tiger.