Monday, October 10, 2022

Improving Firefox Responsiveness on macOS

Gabriele Svelto (tweet, Hacker News):

Performance in some of our automated tests degraded by as much as 30%. os_unfair_lock might be better behaved than OSSpinLock, but it sucked.

As it turns out os_unfair_lock doesn’t spin on contention, it makes the calling thread sleep right away when it finds a contended lock.

For the memory allocator this behavior was suboptimal and the performance regression unacceptable.


However, as I dug into Apple’s libraries and kernel, I noticed that some spin locks were indeed available, and they did the spinning in kernel-space where they could make a more informed choice with regards to load and scheduling. Those would have been an excellent choice for our use-case.

So how do you use them? Well, it turns out they’re not documented. They rely on a non-public function and flags which I had to duplicate in Firefox.

The function is os_unfair_lock_with_options() and the options I used are OS_UNFAIR_LOCK_DATA_SYNCHRONIZATION and OS_UNFAIR_LOCK_ADAPTIVE_SPIN.

Jeff Johnson:

This only works because Firefox is not in the Mac App Store.


Update (2022-10-11): David Smith:

As a heads up, it is VERY easy to shoot yourself in the foot with the data synchronization flag there. It basically gets you something like Swift Concurrency pool behavior, but without the guardrails.

Update (2022-10-17): Oliver Hunt:

In case any one is interested, a few years ago on the @webkit blog, @filpizlo wrote quite a detailed post on how you could implement the high performance locks you might need when you’re replacing system libraries & so don’t use locks like typical apps[…]

There’s now a pull request to use os_unfair_lock_with_options() in WebKit (via dpogue), however it seems to not improve on what WebKit is already doing.

1 Comment RSS · Twitter

heh, it looks like the WebKit devs saw the Mozilla post and decided to try it for themselves:

Leave a Comment