{"id":2798,"date":"2014-06-03T17:17:44","date_gmt":"2014-06-03T22:17:44","guid":{"rendered":"http:\/\/www.splasmata.com\/?p=2798"},"modified":"2014-06-05T10:06:25","modified_gmt":"2014-06-05T15:06:25","slug":"swift","status":"publish","type":"post","link":"https:\/\/www.splasmata.com\/?p=2798","title":{"rendered":"Swift?"},"content":{"rendered":"<p><em>About how swift Apple&#8217;s new programming language isn&#8217;t.<\/em><\/p>\n<p><em><strong>Update:<\/strong> \u00c2\u00a0Hi there! \u00c2\u00a0I&#8217;m humbled to tell you that, as a few readers have pointed out, the original Swift and Objective-C results\u00c2\u00a0in this post were taken from unoptimized builds. \u00c2\u00a0We rebuilt the evening of 6\/4 with optimizations turned on (-O), and ensured\u00c2\u00a0compiler optimization of dead code, ie. assignments being culled because their results aren&#8217;t used later, is not a factor (you&#8217;d see results\u00c2\u00a0orders of magnitude faster, and when we increase the magnitude of our loop count we\u00c2\u00a0do see results an order of magnitude slower). \u00c2\u00a0We used Swift&#8217;s Ints and C&#8217;s ints unless otherwise noted. \u00c2\u00a0With\u00c2\u00a0adjusted numbers in-hand, this post has become something of a living document. \u00c2\u00a0Look for new numbers and notes (some stricken!) throughout. \u00c2\u00a0-Keith<\/em><\/p>\n<p><a title=\"Swift\" href=\"http:\/\/developer.apple.com\/swift\" target=\"_blank\">Swift<\/a> may be the best thing happening to development on the Mac and iOS right now, with a lot of modern features that&#8217;ll help developers new to our platforms and, potentially, make life easier for the older curmudgeons. \u00c2\u00a0There\u00e2\u20ac\u2122s one thing that\u00e2\u20ac\u2122s stuck in my craw since the big reveal yesterday, though:\u00c2\u00a0 Apple would have you believe Swift is, well, <i>swift.<\/i>\u00c2\u00a0 But rewind that <a title=\"WWDC 2014 Keynote Video\" href=\"http:\/\/www.apple.com\/apple-events\/june-2014\/\" target=\"_blank\">keynote video<\/a>, babe, back to about the 105:00 mark.\u00c2\u00a0 Stop staring at Craig\u00e2\u20ac\u2122s hair. \u00c2\u00a0Listen.\u00c2\u00a0 Really listen. \u00c2\u00a0Yep, there&#8217;s applause at the initial announcement, but keep listening. \u00c2\u00a0Three or four sad claps at the first benchmark comparison and zero at the second.<\/p>\n<p>Why is that?<\/p>\n<p><i>Because no one in the room bought it?<\/i><\/p>\n<p>Being somewhat sensitive to most performance claims myself, I set up a test app in both Swift and Objective-C.\u00c2\u00a0 Loop a million times, perform a few esoteric bits each time through the loop.\u00c2\u00a0 Run the code three times, average the elapsed time. \u00c2\u00a0Tweak here and there to try to get the best numbers.<\/p>\n<p>Here\u00e2\u20ac\u2122s what happened:<\/p>\n<p>&nbsp;<\/p>\n<p><b>Loop a million times<\/b><\/p>\n<p>Swift: \u00c2\u00a0<del>0.0036s<\/del> 0.00061s<\/p>\n<p>Objective-C: \u00c2\u00a0<del>0.0021s\u00c2\u00a0(1.7x faster)<\/del>\u00c2\u00a00.000021s\u00c2\u00a0<strong>(29x\u00c2\u00a0faster)<\/strong><\/p>\n<p><del>No work done in the inner loop, just iterate.<\/del>\u00c2\u00a0 Swift actually performs pretty well here. \u00c2\u00a0It&#8217;s a straight C exercise on the Objective-C side, with a conditional assignment in the inner loop to guarantee the compiler didn&#8217;t optimize the loop out entirely.\u00c2\u00a0 <del>Note that in Swift I used a for loop with an index variable incremented with x = x + 1, because ++ is far slower and for _ in 0\u00e2\u20ac\u00a6999999 is glacial.<\/del><\/p>\n<p>&nbsp;<\/p>\n<p><b>Increment<\/b><\/p>\n<p>Swift: \u00c2\u00a0<del>0.024s<\/del> 0.00092s<\/p>\n<p>Objective-C: \u00c2\u00a0<del>0.0023s\u00c2\u00a0(10.4x faster)<\/del>\u00c2\u00a00.00002s\u00c2\u00a0<strong>(46x faster)<\/strong><\/p>\n<p><del>Strangely, Swift has a major performance issue with the ++ operator.\u00c2\u00a0 It\u00e2\u20ac\u2122s roughly 6x <strong>s l o w e r<\/strong> than x = x + 1, which is the basic code I used to get the best performance.<\/del>\u00c2\u00a0 On the Objective-C side, we placed a conditional assignment in the inner loop to guarantee the compiler didn&#8217;t optimize the loop out entirely.<\/p>\n<p>&nbsp;<\/p>\n<p><b>Assign<\/b><\/p>\n<p>Swift: \u00c2\u00a0<del>0.024s<\/del> 0.00066s<\/p>\n<p>Objective-C: \u00c2\u00a0<del>0.0022s (10.9x faster)<\/del>\u00c2\u00a00.000021s\u00c2\u00a0<strong>(31.4x faster)<\/strong><\/p>\n<p>This is a simple x = y.<\/p>\n<p>Yeowch. \u00c2\u00a0I&#8217;m guessing Automatic Reference Counting is involved on the Swift side. \u00c2\u00a0Retaining and releasing a million times would bring on the hurt.\u00c2\u00a0 On the Objective-C side, we placed a conditional assignment in the inner loop to guarantee the compiler didn&#8217;t optimize the loop out entirely.<\/p>\n<p>&nbsp;<\/p>\n<p><b>Append native string to native array<\/b><\/p>\n<p>Swift: \u00c2\u00a0<del>6.49s<\/del> 0.33s<\/p>\n<p>Objective-C: \u00c2\u00a0<del>0.046s (141.1x faster)<\/del>\u00c2\u00a00.042\u00c2\u00a0<strong>(7.9x faster)<\/strong><\/p>\n<p>In Swift I used an Array of String.\u00c2\u00a0 In Objective-C I added an NSString to an NSMutableArray with no optimizations or tweaks.\u00c2\u00a0 It would be even faster if we dropped to CFMutableArrayRef because in so many cases you don\u00e2\u20ac\u2122t need to retain what you add to an array, something NSMutableArray does automatically &#8211; and, behind the scenes, Swift is almost surely doing the same because of how Automatic Reference Counting works.\u00c2\u00a0 Straight C arrays would be blinding.\u00c2\u00a0 ARC is not a performance optimization.<\/p>\n<p>&nbsp;<\/p>\n<p><b>Append native integer to native array<\/b><\/p>\n<p>Swift: \u00c2\u00a0<del>6.51s<\/del> 0.3s<\/p>\n<p>Objective-C: \u00c2\u00a0<del>0.023s (283x faster)<\/del> 0.023s <strong>(13x faster)<\/strong><\/p>\n<p>In Swift I used an Array of Int.\u00c2\u00a0 In Objective-C I added an NSNumber to an NSMutableArray with no optimizations or tweaks.\u00c2\u00a0 It would be even faster if we dropped to CFMutableArrayRef because in so many cases you don\u00e2\u20ac\u2122t need to retain what you add to an array, something NSMutableArray does automatically &#8211; and, behind the scenes, Swift is almost surely doing the same because of how Automatic Reference Counting works.\u00c2\u00a0 Straight C arrays would be blinding.\u00c2\u00a0 <b>ARC is not a performance optimization.<\/b><\/p>\n<p>&nbsp;<\/p>\n<p><b>Concatenate two strings<\/b><\/p>\n<p>Swift: \u00c2\u00a0<del>3.47s<\/del> 3.15s<\/p>\n<p>Objective-C: \u00c2\u00a0<del>0.27s (21x faster)<\/del>\u00c2\u00a00.27s <strong>(11.7 faster)<\/strong><\/p>\n<p>In Swift, the inner loop looked like this:<\/p>\n<p><em>\u00c2\u00a0 \u00c2\u00a0 theString3 = theString + theString2<\/em><\/p>\n<p>In Objective-C, the inner loop looked like this:<\/p>\n<p><em>\u00c2\u00a0 \u00c2\u00a0 theString3 = [theString stringByAppendingString:theString2];<\/em><\/p>\n<p>&nbsp;<\/p>\n<p><b>What\u00e2\u20ac\u2122s the deal?<\/b><\/p>\n<p>We can&#8217;t know exactly what&#8217;s going on behind the scenes, but my hunch is some\u00c2\u00a0of what we take for granted in Objective-C &#8211; the straight C scalar data types &#8211; are actually classes in Swift. \u00c2\u00a0And the more you rely on classes, the more Automatic Reference Counting is in there somewhere, retaining and releasing like there&#8217;s no tomorrow, often for no good reason.<\/p>\n<p>Coders are constantly balancing trade-offs.\u00c2\u00a0 Raw performance isn\u00e2\u20ac\u2122t always the priority, because you have to conceptualize, code, iterate, debug, extend, refactor, share, ship, maintain, and support.\u00c2\u00a0 One team\u00e2\u20ac\u2122s acceptable trade is another team\u00e2\u20ac\u2122s hell stew.\u00c2\u00a0 For example, we don\u00e2\u20ac\u2122t use &#8211; <strong>surprise!<\/strong> &#8211; Automatic Reference Counting at <a title=\"Splasm Software:  Thoughtful apps given form\" href=\"http:\/\/splasm.com\" target=\"_blank\">Splasm<\/a> because, frankly, it\u00e2\u20ac\u2122s around 40% slower in some cases, so we&#8217;ll leave ARC off and\u00c2\u00a0take that 40% back (and we enjoy manual memory management, thank you very much).\u00c2\u00a0 Other teams wouldn\u00e2\u20ac\u2122t give up ARC even if paint dried faster. \u00c2\u00a0Did I say &#8216;if&#8217;? \u00c2\u00a0Different teams.\u00c2\u00a0 Different values.<\/p>\n<p>Swift has performance issues in our tests that other teams won\u00e2\u20ac\u2122t be concerned about.\u00c2\u00a0 It\u00e2\u20ac\u2122s also a very new language that Apple will improve over time.\u00c2\u00a0 Though Apple claims big performance gains, we think comparing Swift to Objective-C right now is a little premature.\u00c2\u00a0 We\u00e2\u20ac\u2122ll continue to play with it, learning and sharing with the community, but for the foreseeable future, unless the performance issues evaporate &#8211; or Apple abandons Objective-C altogether &#8211; we\u00e2\u20ac\u2122ll be developing in Objective-C.\u00c2\u00a0 It has its issues, but well-established design patterns, direct control of memory, more readable (and self-documenting) code, and terrific performance for our users are not among them.<\/p>\n<p><em>Note that the original results were taken from unoptimized builds. \u00c2\u00a0When we rebuilt, Swift became much swifter in some cases and slower, relatively, in others. \u00c2\u00a0The closest it came\u00c2\u00a0to Objective-C&#8217;s performance was a factor of 6.4x slower, and that was in a test we didn&#8217;t show results for (appending to an NSMutableArray instead of an Int array in Swift). \u00c2\u00a0We&#8217;re considering porting a small project over to Swift sooner than later to get a better idea of real world numbers&#8230;and we&#8217;ll share those when we have them!<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>About how swift Apple&#8217;s new programming language isn&#8217;t. Update: \u00c2\u00a0Hi there! \u00c2\u00a0I&#8217;m humbled to tell you that, as a few readers have pointed out, the original Swift and Objective-C results\u00c2\u00a0in this post were taken from unoptimized builds. \u00c2\u00a0We rebuilt the &hellip; <a href=\"https:\/\/www.splasmata.com\/?p=2798\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3,1,7],"tags":[],"class_list":["post-2798","post","type-post","status-publish","format-standard","hentry","category-development","category-general","category-opinion"],"_links":{"self":[{"href":"https:\/\/www.splasmata.com\/index.php?rest_route=\/wp\/v2\/posts\/2798","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.splasmata.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.splasmata.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.splasmata.com\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.splasmata.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2798"}],"version-history":[{"count":23,"href":"https:\/\/www.splasmata.com\/index.php?rest_route=\/wp\/v2\/posts\/2798\/revisions"}],"predecessor-version":[{"id":2822,"href":"https:\/\/www.splasmata.com\/index.php?rest_route=\/wp\/v2\/posts\/2798\/revisions\/2822"}],"wp:attachment":[{"href":"https:\/\/www.splasmata.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2798"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.splasmata.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2798"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.splasmata.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2798"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}