{"id":23981,"date":"2019-01-17T17:02:20","date_gmt":"2019-01-17T22:02:20","guid":{"rendered":"https:\/\/mjtsai.com\/blog\/?p=23981"},"modified":"2019-01-23T14:05:05","modified_gmt":"2019-01-23T19:05:05","slug":"stack-allocation-for-non-escaping-swift-closures","status":"publish","type":"post","link":"https:\/\/mjtsai.com\/blog\/2019\/01\/17\/stack-allocation-for-non-escaping-swift-closures\/","title":{"rendered":"Stack Allocation for Non-Escaping Swift Closures"},"content":{"rendered":"<p><a href=\"https:\/\/github.com\/apple\/swift\/pull\/21933\">aschwaighofer<\/a> has a pull request for stack-allocating Swift closures.<\/p>\n\n<p><a href=\"https:\/\/twitter.com\/slava_pestov\/status\/1085691914328920066\">Slava Pestov<\/a>:<\/p>\n<blockquote cite=\"https:\/\/twitter.com\/slava_pestov\/status\/1085691914328920066\">\n<p>Short history of non-escaping functions:<\/p>\n<p>- Swift 4.1 and earlier: type checker enforcement; same ABI as escaping<br \/>\n- Swift 4.2: new ABI - the context is a trivial pointer and not ref-counted like with escaping<br \/>\n- now: non-escaping contexts allocated on stack<\/p>\n<p>The ABI change was key here - Arnold frontloaded the changes before we started locking down, now stack-allocation is &ldquo;just&rdquo; an optimization<\/p>\n<p>And ancient pre-history for those who weren&rsquo;t around at the time:<\/p>\n<p>- Swift 2.2 and earlier: all function values escaping by default, opt-in @noescape attribute for parameter types<br \/>\n- Swift 3: @noescape becomes default for function parameters, @escaping added to opt-in<\/p>\n<p>More trivia: In ancient Swift the accepted idiom to turn a non-escaping function into an escaping one was unfortunately an unsafeBitCast(). The compiler added a special withoutActuallyEscaping form and started screaming about casts in 4.0 so that we could stage in the ABI change<\/p>\n<\/blockquote>\n\n<p>Previously: <a href=\"https:\/\/mjtsai.com\/blog\/2016\/10\/11\/optional-non-escaping-swift-closures\/\">Optional Non-Escaping Swift Closures<\/a>.<\/p>\n\n<p id=\"stack-allocation-for-non-escaping-swift-closures-update-2019-01-23\">Update (2019-01-23): <a href=\"https:\/\/twitter.com\/cocoawithlove\/status\/1086581405625180161\">Matt Gallagher<\/a>:<\/p>\n<blockquote cite=\"https:\/\/twitter.com\/cocoawithlove\/status\/1086581405625180161\"><p>I played around with Swift master&rsquo;s new stack allocated closure contexts today. My &ldquo;capturing closure&rdquo; mutex test case from <a href=\"http:\/\/www.cocoawithlove.com\/blog\/2016\/06\/02\/threads-and-mutexes.html\">this article<\/a> improved 10x from 2.051 seconds to 0.212 seconds. Putting it within 20% of the inlined version.<\/p><p>Unfortunately, I needed to disable runtime exclusivity checking to get this performance. With exclusivity on, performance was 0.384 seconds (nearly 100% slower). Seems like this code should be statically checkable for exclusivity. Hope this improves.<\/p><p>Another unfortunate point: DispatchQueue.sync&rsquo;s closure still isn&rsquo;t optimized to the stack. I think this is a consequence of the stdlib&rsquo;s interface around <code>dispatch_queue_sync<\/code>. I hope it gets resolved soon. I&rsquo;d rather just use DispatchQueue.sync and not worry about performance.<\/p><\/blockquote>\n<p><a href=\"https:\/\/twitter.com\/olebegemann\/status\/1086592710344093696\">Ole Begemann<\/a>:<\/p>\n<blockquote cite=\"https:\/\/twitter.com\/olebegemann\/status\/1086592710344093696\">\n<p>Stack allocation <a href=\"https:\/\/bugs.swift.org\/browse\/SR-9701\">doesn&rsquo;t work yet<\/a> for Objective-C blocks. I suspect that also applies to wrappers like DispatchQueue.sync.<\/p>\n<\/blockquote>","protected":false},"excerpt":{"rendered":"<p>aschwaighofer has a pull request for stack-allocating Swift closures. Slava Pestov: Short history of non-escaping functions: - Swift 4.1 and earlier: type checker enforcement; same ABI as escaping - Swift 4.2: new ABI - the context is a trivial pointer and not ref-counted like with escaping - now: non-escaping contexts allocated on stack The ABI [&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":"2019-01-17T22:02:22Z","apple_news_api_id":"80d551c0-3a69-41dc-8fda-252e45e7a35c","apple_news_api_modified_at":"2019-01-23T19:05:11Z","apple_news_api_revision":"AAAAAAAAAAAAAAAAAAAAAQ==","apple_news_api_share_url":"https:\/\/apple.news\/AgNVRwDppQdyP2iUuReejXA","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":[],"tags":[255,46,138,71,901],"class_list":["post-23981","post","type-post","status-publish","format-standard","hentry","tag-compiler","tag-languagedesign","tag-optimization","tag-programming","tag-swift-programming-language"],"apple_news_notices":[],"_links":{"self":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/23981","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=23981"}],"version-history":[{"count":2,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/23981\/revisions"}],"predecessor-version":[{"id":24031,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/23981\/revisions\/24031"}],"wp:attachment":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/media?parent=23981"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/categories?post=23981"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/tags?post=23981"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}