{"id":37291,"date":"2022-10-10T16:57:50","date_gmt":"2022-10-10T20:57:50","guid":{"rendered":"https:\/\/mjtsai.com\/blog\/?p=37291"},"modified":"2022-10-17T15:52:17","modified_gmt":"2022-10-17T19:52:17","slug":"improving-firefox-responsiveness-on-macos","status":"publish","type":"post","link":"https:\/\/mjtsai.com\/blog\/2022\/10\/10\/improving-firefox-responsiveness-on-macos\/","title":{"rendered":"Improving Firefox Responsiveness on macOS"},"content":{"rendered":"<p><a href=\"https:\/\/hacks.mozilla.org\/2022\/10\/improving-firefox-responsiveness-on-macos\/\">Gabriele Svelto<\/a> (<a href=\"https:\/\/twitter.com\/mozhacks\/status\/1579490902057578496\">tweet<\/a>, <a href=\"https:\/\/news.ycombinator.com\/item?id=33152472\">Hacker News<\/a>):<\/p>\n<blockquote cite=\"https:\/\/hacks.mozilla.org\/2022\/10\/improving-firefox-responsiveness-on-macos\/\"><p>Performance in some of our automated tests <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=1774458\">degraded by as much as 30%<\/a>. <code>os_unfair_lock<\/code> might be better behaved than <code>OSSpinLock<\/code>, but it sucked.<\/p><p>As it turns out <code>os_unfair_lock<\/code> doesn&rsquo;t spin on contention, it makes the calling thread <a href=\"https:\/\/github.com\/apple\/darwin-libplatform\/blob\/215b09856ab5765b7462a91be7076183076600df\/src\/os\/lock.c#L536\">sleep right away when it finds a contended lock<\/a>.<\/p><p>For the memory allocator this behavior was suboptimal and the performance regression unacceptable.<\/p><p>[&#8230;]<\/p><p>However, as I dug into Apple&rsquo;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.<\/p><p>So how do you use them? Well, it turns out they&rsquo;re not documented. They rely on a non-public function and flags which I had to duplicate in Firefox.<\/p><p>The function is <a href=\"https:\/\/searchfox.org\/mozilla-central\/rev\/6ec440e105c2b75d5cae9d34f957a2f85a106d54\/memory\/build\/Mutex.h#22-34\"><code>os_unfair_lock_with_options()<\/code><\/a> and the options I used are <code>OS_UNFAIR_LOCK_DATA_SYNCHRONIZATION<\/code> and <code>OS_UNFAIR_LOCK_ADAPTIVE_SPIN<\/code>.<\/p><\/blockquote>\n\n<p><a href=\"https:\/\/twitter.com\/lapcatsoftware\/status\/1579506308494942208\">Jeff Johnson<\/a>:<\/p>\n<blockquote cite=\"https:\/\/twitter.com\/lapcatsoftware\/status\/1579506308494942208\">\n<p>This only works because Firefox is not in the Mac App Store.<\/p>\n<\/blockquote>\n\n<p>Previously:<\/p>\n<ul>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2020\/01\/06\/beware-spinlocks-in-user-space\/\">Beware Spinlocks in User Space<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2017\/10\/30\/locks-thread-safety-and-swift-2017-edition\/\">Locks, Thread Safety, and Swift: 2017 Edition<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2016\/10\/07\/os_unfair_lock\/\">os_unfair_lock<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2015\/12\/16\/osspinlock-is-unsafe\/\">OSSpinLock Is Unsafe<\/a><\/li>\n<\/ul>\n\n<p id=\"improving-firefox-responsiveness-on-macos-update-2022-10-11\">Update (2022-10-11): <a href=\"https:\/\/twitter.com\/Catfish_Man\/status\/1579598240932319234\">David Smith<\/a>:<\/p>\n<blockquote cite=\"https:\/\/twitter.com\/Catfish_Man\/status\/1579598240932319234\">\n<p>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.<\/p>\n<\/blockquote>\n\n<p id=\"improving-firefox-responsiveness-on-macos-update-2022-10-17\">Update (2022-10-17): <a href=\"https:\/\/twitter.com\/ohunt\/status\/1579645630376742913\">Oliver Hunt<\/a>:<\/p>\n<blockquote cite=\"https:\/\/twitter.com\/ohunt\/status\/1579645630376742913\">\n<p>In case any one is interested, a few years ago on the \n@webkit\n blog, \n@filpizlo\n wrote quite a <a href=\"https:\/\/webkit.org\/blog\/6161\/locking-in-webkit\/\">detailed post<\/a> on how you could implement the high performance locks you might need when you&rsquo;re replacing system libraries &amp; so don&rsquo;t use locks like typical apps[&#8230;]<\/p>\n<\/blockquote>\n\n<p>There&rsquo;s now a <a href=\"https:\/\/github.com\/WebKit\/WebKit\/pull\/5266\">pull request<\/a> to use <code>os_unfair_lock_with_options()<\/code> in WebKit (via <a href=\"https:\/\/mjtsai.com\/blog\/2022\/10\/10\/improving-firefox-responsiveness-on-macos\/#comment-3820033\">dpogue<\/a>), however it seems to <a href=\"https:\/\/github.com\/WebKit\/WebKit\/pull\/5266#issuecomment-1279933973\">not improve on<\/a> what WebKit is already doing.<\/p>","protected":false},"excerpt":{"rendered":"<p>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&rsquo;t spin on contention, it makes the calling thread sleep right away when it finds a contended lock.For the memory allocator this behavior [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"apple_news_api_created_at":"2022-10-10T20:57:53Z","apple_news_api_id":"f2b50a4d-8e1b-4941-8f33-192c250f1652","apple_news_api_modified_at":"2022-10-17T19:52:20Z","apple_news_api_revision":"AAAAAAAAAAAAAAAAAAAAAw==","apple_news_api_share_url":"https:\/\/apple.news\/A8rUKTY4bSUGPMxksJQ8WUg","apple_news_coverimage":0,"apple_news_coverimage_caption":"","apple_news_is_hidden":false,"apple_news_is_paid":false,"apple_news_is_preview":false,"apple_news_is_sponsored":false,"apple_news_maturity_rating":"","apple_news_metadata":"\"\"","apple_news_pullquote":"","apple_news_pullquote_position":"","apple_news_slug":"","apple_news_sections":"\"\"","apple_news_suppress_video_url":false,"apple_news_use_image_component":false,"footnotes":""},"categories":[4],"tags":[800,279,30,32,39,1666,2077,138,1013,71,328],"class_list":["post-37291","post","type-post","status-publish","format-standard","hentry","category-programming-category","tag-concurrency","tag-firefox","tag-mac","tag-macapp","tag-macappstore","tag-macos-10-15","tag-macos-12","tag-optimization","tag-private-api","tag-programming","tag-webkit"],"apple_news_notices":[],"_links":{"self":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/37291","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/comments?post=37291"}],"version-history":[{"count":5,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/37291\/revisions"}],"predecessor-version":[{"id":37351,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/37291\/revisions\/37351"}],"wp:attachment":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/media?parent=37291"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/categories?post=37291"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/tags?post=37291"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}