{"id":20842,"date":"2018-03-09T11:52:07","date_gmt":"2018-03-09T16:52:07","guid":{"rendered":"https:\/\/mjtsai.com\/blog\/?p=20842"},"modified":"2018-03-10T14:06:35","modified_gmt":"2018-03-10T19:06:35","slug":"faster-swift-string-concatenation","status":"publish","type":"post","link":"https:\/\/mjtsai.com\/blog\/2018\/03\/09\/faster-swift-string-concatenation\/","title":{"rendered":"Faster Swift String Concatenation"},"content":{"rendered":"<p><a href=\"https:\/\/twitter.com\/nicklockwood\/status\/971506873387143168\">Nick Lockwood<\/a>:<\/p>\n<blockquote cite=\"https:\/\/twitter.com\/nicklockwood\/status\/971506873387143168\"><p>I&rsquo;m sure I heard somewhere that <code>\"\\(foo)\\(bar)\"<\/code> is the recommended way to do string concatenation in Swift, but I benchmarked it and it&rsquo;s almost 100x slower than using <code>+<\/code> or <code>String.append()<\/code>.<\/p><\/blockquote>\n<p>I know I&rsquo;ve heard that as well. I assumed it was taken as a hint to figure out the proper allocation size up front. But currently it&rsquo;s slower because the interpolated elements are not assumed to be strings.<\/p>\n\n<p><a href=\"https:\/\/twitter.com\/jckarter\/status\/971515495743549440\">Joe Groff<\/a>:<\/p>\n<blockquote cite=\"https:\/\/twitter.com\/jckarter\/status\/971515495743549440\">\n<p>Yeah, <code>\\(x)<\/code> goes through the print-anything path for <code>x<\/code>, which hasn&rsquo;t really been optimized<\/p>\n<\/blockquote>\n\n<p><a href=\"https:\/\/twitter.com\/SteveBarnegren\/status\/971511496416092160\">Steve Barnegren<\/a>:<\/p>\n<blockquote cite=\"https:\/\/twitter.com\/SteveBarnegren\/status\/971511496416092160\">\n<p>I thought that the recommendation to use <code>\"\\(foo)\\(bar)\"<\/code> over <code>+<\/code> was more for compilation performance than runtime performance, as the compiler has to work to understand which <code>+<\/code> operator to use.<\/p>\n<\/blockquote>\n\n<p><a href=\"http:\/\/www.globalnerdy.com\/2016\/02\/03\/concatenating-strings-in-swift-which-way-is-faster\/\">Joey Devilla<\/a>:<\/p>\n<blockquote cite=\"http:\/\/www.globalnerdy.com\/2016\/02\/03\/concatenating-strings-in-swift-which-way-is-faster\/\"><p>Running on the phone, the <code>+<\/code> method is almost 70 times faster, which is a significant difference when concatenating a large number &mdash; 100 million &mdash; strings. If you&rsquo;re concatenating far fewer strings, your better bet is to go with the option that gives you the more readable, editable code.<\/p><\/blockquote>\n\n<p><a href=\"https:\/\/twitter.com\/mpweiher\/status\/971674571735814144\">Marcel Weiher<\/a>:<\/p>\n<blockquote cite=\"https:\/\/twitter.com\/mpweiher\/status\/971674571735814144\">\n<p>A factor 100 here, a factor 100 there, soon enough&#8230; &macr;\\_(&#x30C4;)_\/&macr;<\/p>\n<\/blockquote>\n\n<p><a href=\"https:\/\/twitter.com\/nicklockwood\/status\/971818763258679301\">Nick Lockwood<\/a>:<\/p>\n<blockquote cite=\"https:\/\/twitter.com\/nicklockwood\/status\/971818763258679301\">\n<p>A lot of people have jumped on this to criticise Swift&rsquo;s maturity as a language.<\/p>\n<p>To put it in context, even at 100x slower, you can still comfortably perform 500,000 string concatenations per second. In most apps this would be a complete non-issue.<\/p>\n<\/blockquote>\n\n<p>Update (2018-03-10): <a href=\"https:\/\/twitter.com\/nicklockwood\/status\/972465739251765248\">Nick Lockwood<\/a>:<\/p>\n<blockquote cite=\"https:\/\/twitter.com\/nicklockwood\/status\/972465739251765248\"><p>Deleted this, since it was due to a misconception on my part.<\/p><\/blockquote>\n<p>His <a href=\"https:\/\/twitter.com\/nicklockwood\/status\/972504409300176897\">original test<\/a> measured <code>foo = \"\\(foo)bar\"<\/code> vs. <code>foo += \"bar\"<\/code>, which is not what I would have expected from the tweet&rsquo;s description. The latter is 100x faster because Swift is able to mutate the string rather than create a new one. The benchmark code is <a href=\"https:\/\/gist.github.com\/nicklockwood\/9a5b846f9535c1f1e5743429a9ccd71f\">here<\/a>.<\/p>\n<p>I measured <code>baz = \"\\(foo)\\(bar)\"<\/code> vs. <code>baz = foo + bar<\/code>, which is what I thought he was originally talking about (i.e not building up a giant string), and found the latter to be about twice as fast, perhaps because of the overhead that Groff mentioned.<\/p>\n<p>Devilla measured <code>newString = \"\\(string1) \\(string2)\"<\/code> vs. <code>newString = string1 + \" \" + string2<\/code> and found the latter to be 70x faster. I tried to reproduce this but found less than 10% difference <em>in the opposite direction<\/em>. In other words, interpolation was slightly faster. However, I am using Swift 4, and he was using Swift 2.<\/p>","protected":false},"excerpt":{"rendered":"<p>Nick Lockwood: I&rsquo;m sure I heard somewhere that \"\\(foo)\\(bar)\" is the recommended way to do string concatenation in Swift, but I benchmarked it and it&rsquo;s almost 100x slower than using + or String.append(). I know I&rsquo;ve heard that as well. I assumed it was taken as a hint to figure out the proper allocation size [&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":[],"tags":[138,71,901],"class_list":["post-20842","post","type-post","status-publish","format-standard","hentry","tag-optimization","tag-programming","tag-swift-programming-language"],"apple_news_notices":[],"_links":{"self":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/20842","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=20842"}],"version-history":[{"count":5,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/20842\/revisions"}],"predecessor-version":[{"id":20852,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/20842\/revisions\/20852"}],"wp:attachment":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/media?parent=20842"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/categories?post=20842"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/tags?post=20842"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}