{"id":14474,"date":"2016-05-09T13:53:58","date_gmt":"2016-05-09T17:53:58","guid":{"rendered":"http:\/\/mjtsai.com\/blog\/?p=14474"},"modified":"2016-06-16T09:36:09","modified_gmt":"2016-06-16T13:36:09","slug":"locking-in-webkit","status":"publish","type":"post","link":"https:\/\/mjtsai.com\/blog\/2016\/05\/09\/locking-in-webkit\/","title":{"rendered":"Locking in WebKit"},"content":{"rendered":"<p><a href=\"https:\/\/webkit.org\/blog\/6161\/locking-in-webkit\/\">Filip Pizlo<\/a> (<a href=\"https:\/\/news.ycombinator.com\/item?id=11644439\">Hacker News<\/a>):<\/p>\r\n<blockquote cite=\"https:\/\/webkit.org\/blog\/6161\/locking-in-webkit\/\">\r\n<p>Compared to OS-provided locks like <code>pthread_mutex<\/code>, <code>WTF::Lock<\/code> is 64 times smaller and up to 180 times faster. Compared to OS-provided condition variables like <code>pthread_cond<\/code>, <code>WTF::Condition<\/code> is 64 times smaller. Using <code>WTF::Lock<\/code> instead of <code>pthread_mutex<\/code> means that WebKit is 10% faster on <a href=\"http:\/\/browserbench.org\/JetStream\/\">JetStream<\/a>, 5% faster on <a href=\"http:\/\/browserbench.org\/Speedometer\/\">Speedometer<\/a>, and 5% faster on our page loading test.<\/p>\r\n<p>Making <code>WTF::Lock<\/code> and <code>WTF::Condition<\/code> fit in one byte is not easy and the technique behind this has multiple layers. <code>Lock<\/code> and <code>Condition<\/code> offload all thread queueing and suspending functionality to <a href=\"http:\/\/trac.webkit.org\/browser\/trunk\/Source\/WTF\/wtf\/ParkingLot.h?rev=200444\"><code>WTF::ParkingLot<\/code><\/a>, which manages thread queues keyed by the addresses of locks. The design of <code>ParkingLot<\/code> is inspired by <a href=\"http:\/\/man7.org\/linux\/man-pages\/man2\/futex.2.html\">futexes<\/a>. <code>ParkingLot<\/code> is a portable user-level implementation of the core futex API. <code>ParkingLot<\/code> also needs fast locks, so we built it its own lock called <a href=\"http:\/\/trac.webkit.org\/browser\/trunk\/Source\/WTF\/wtf\/WordLock.h?rev=200444\"><code>WTF::WordLock<\/code><\/a>.<\/p>\r\n<p>[&#8230;]<\/p>\r\n<p>Adaptive locks combine parking and spinning. Spinning is great because it protects microcontention scenarios from doing parking. Microcontention is when a thread fails the fast path lock acquisition because the lock is not available right now, but that lock will become available in less time than what it would take to park and then unpark. Before <code>WTF::Lock::lock()<\/code> parks a thread, it will spin 40 times, calling <a href=\"http:\/\/pubs.opengroup.org\/onlinepubs\/009695399\/functions\/sched_yield.html\">yield<\/a> between spins.<\/p>\r\n<p>[&#8230;]<\/p>\r\n<p>One advantage of OS mutexes is that they guarantee fairness: All threads waiting for a lock form a queue, and, when the lock is released, the thread at the head of the queue acquires it. It&rsquo;s 100% deterministic. While this kind of behavior makes mutexes easier to reason about, it reduces throughput because it prevents a thread from reacquiring a mutex it just released. It&rsquo;s common for WebKit threads to repeatedly acquire the same lock.<\/p>\r\n<p>[&#8230;]<\/p>\r\n<p>It&rsquo;s clear that the OS mutex is doing exactly what it set out to do: no thread gets to do any more work than any other thread. On the other hand, <code>WTF::Lock<\/code> does not guarantee fairness. Analysis of the algorithm shows that a thread that has been waiting the longest to get the lock may fail to get the lock and be forced to go to the end of the queue. But this chart shows that even without having a fairness guarantee, the unluckiest thread using <code>WTF::Lock<\/code> got better treatment than any thread using the guaranteed-fair mutex. It&rsquo;s almost as if the OS mutex is not actually fair because while thread 1 is served equally to thread 2, all 10 threads are underserved relative to a hypothetical thread 11, which is using a different algorithm. Indeed, we can think of thread 11 as being the OS context switch handler.<\/p>\r\n<\/blockquote>","protected":false},"excerpt":{"rendered":"<p>Filip Pizlo (Hacker News): Compared to OS-provided locks like pthread_mutex, WTF::Lock is 64 times smaller and up to 180 times faster. Compared to OS-provided condition variables like pthread_cond, WTF::Condition is 64 times smaller. Using WTF::Lock instead of pthread_mutex means that WebKit is 10% faster on JetStream, 5% faster on Speedometer, and 5% faster on our [&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":"","apple_news_api_id":"","apple_news_api_modified_at":"","apple_news_api_revision":"","apple_news_api_share_url":"","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,31,1137,30,1199,138,71,96,328],"class_list":["post-14474","post","type-post","status-publish","format-standard","hentry","category-programming-category","tag-concurrency","tag-ios","tag-ios-9","tag-mac","tag-mac-os-x-10-11","tag-optimization","tag-programming","tag-web","tag-webkit"],"apple_news_notices":[],"_links":{"self":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/14474","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=14474"}],"version-history":[{"count":2,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/14474\/revisions"}],"predecessor-version":[{"id":14818,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/14474\/revisions\/14818"}],"wp:attachment":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/media?parent=14474"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/categories?post=14474"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/tags?post=14474"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}