{"id":375,"date":"2008-09-22T20:38:25","date_gmt":"2008-09-22T08:38:25","guid":{"rendered":"https:\/\/www.deltics.co.nz\/blog\/?p=375"},"modified":"2009-08-07T14:58:26","modified_gmt":"2009-08-07T02:58:26","slug":"delphi-2009-stringperformance-redux","status":"publish","type":"post","link":"https:\/\/www.deltics.co.nz\/blog\/posts\/375\/","title":{"rendered":"Delphi 2009 &#8211; StringPerformance Redux"},"content":{"rendered":"<span class=\"rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">[Estimated Reading Time: <\/span> <span class=\"rt-time\">3<\/span> <span class=\"rt-label rt-postfix\">minutes]<\/span><\/span><p>It looks like I may have jumped the gun with my conclusions from the previous exercise to benchmark string performance in Delphi 2009.\u00a0 Following a <a href=\"https:\/\/www.deltics.co.nz\/blog\/?p=349#comments\" target=\"_blank\">useful exchange in the comments with Kryvich<\/a> I corrected a small discrepancy in the tests and made some changes to the performance testing subsystem within the SmokeTest framework.\u00a0 I then re-ran my string performance benchmarks with some significant &#8211; and more encouraging &#8211; differences in the results.<\/p>\n<p><!--more--><\/p>\n<p>I shall not go into the specifics of the tests again &#8211; if you&#8217;re interested and missed it the first time around you can read my <a href=\"https:\/\/www.deltics.co.nz\/blog\/?p=349\" target=\"_blank\">previous post<\/a>.<\/p>\n<p>The major changes were made in the SmokeTest performance testing subsystem itself:<\/p>\n<p style=\"padding-left: 30px;\">1. Corrected a bug in the CPU affinity code (oops!)<\/p>\n<p style=\"padding-left: 30px;\">2. Implemented CPU instruction cache flushing<\/p>\n<p>The CPU affinity fix now correctly ensures that the code under test is executed on the 2nd processor in any N-core or N-processor hardware.\u00a0 The main thread of the SmokeTest framework application itself is assigned to the 1st CPU.<\/p>\n<p>This is intended to eliminate context switching artefacts and main thread impact from the code under test.\u00a0 The bug was that the main thread was inadvertently allowed to run on all available CPU&#8217;s &#8211; the impact on test results is negligible I think, but even so.<\/p>\n<p>The CPU instruction cache flushing has a much more significant impact and is performed following each execution of a method under test.\u00a0 This has had a significant impact on the raw numbers coming out of the test results (i.e. the number of executions completed per second) but should ensure that the performance of the code itself is tested, not the efficiency of the CPU cache.<\/p>\n<p>The source code being tested is essentially unchanged from that previously used, although it contained one minor correction to the Indexing test case already <a href=\"https:\/\/www.deltics.co.nz\/blog\/?p=349#comments\" target=\"_blank\">documented in the comments<\/a> of that previous post.<\/p>\n<p>I have updated the results download with the new data.\u00a0 This time I have included the Excel spreadsheet with the pretty formatting of the results data comparison and also all three of the raw results files emitted in CSV format by the test app itself.<\/p>\n<h2>Observations On The New Results<\/h2>\n<p>The new test results actually fit more intuitively with what we might expect, albeit still with one or two noteworthy results.<\/p>\n<p><a href=\"https:\/\/i0.wp.com\/www.deltics.co.nz\/blog\/wp-content\/uploads\/delphi2009-stringperformance-resultscapture-redux.jpg?ssl=1\"><img decoding=\"async\" loading=\"lazy\" class=\"size-full wp-image-380 alignleft\" title=\"delphi2009-stringperformance-resultscapture-redux\" src=\"https:\/\/i0.wp.com\/www.deltics.co.nz\/blog\/wp-content\/uploads\/delphi2009-stringperformance-resultscapture-redux.jpg?resize=300%2C281&#038;ssl=1\" alt=\"\" width=\"300\" height=\"281\" srcset=\"https:\/\/i0.wp.com\/www.deltics.co.nz\/blog\/wp-content\/uploads\/delphi2009-stringperformance-resultscapture-redux.jpg?w=847&amp;ssl=1 847w, https:\/\/i0.wp.com\/www.deltics.co.nz\/blog\/wp-content\/uploads\/delphi2009-stringperformance-resultscapture-redux.jpg?resize=300%2C281&amp;ssl=1 300w\" sizes=\"(max-width: 300px) 100vw, 300px\" data-recalc-dims=\"1\" \/><\/a><a href=\"https:\/\/i0.wp.com\/www.deltics.co.nz\/blog\/wp-content\/uploads\/delphi2009-stringperformance-chart.jpg?ssl=1\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-385\" title=\"delphi2009-stringperformance-chart\" src=\"https:\/\/i0.wp.com\/www.deltics.co.nz\/blog\/wp-content\/uploads\/delphi2009-stringperformance-chart.jpg?resize=300%2C252&#038;ssl=1\" alt=\"\" width=\"300\" height=\"252\" srcset=\"https:\/\/i0.wp.com\/www.deltics.co.nz\/blog\/wp-content\/uploads\/delphi2009-stringperformance-chart.jpg?w=869&amp;ssl=1 869w, https:\/\/i0.wp.com\/www.deltics.co.nz\/blog\/wp-content\/uploads\/delphi2009-stringperformance-chart.jpg?resize=300%2C252&amp;ssl=1 300w\" sizes=\"(max-width: 300px) 100vw, 300px\" data-recalc-dims=\"1\" \/><\/a><\/p>\n<p style=\"text-align: center;\">\n<p style=\"text-align: center;\">[dm]10[\/dm]<\/p>\n<p style=\"padding-left: 30px;\">1. Overall Unicode string performance is about 5-10% less efficient than ANSI string handling in Delphi 2007 but is comparable to and in many cases generally improved when compared to Delphi 7.<\/p>\n<p style=\"padding-left: 30px;\">2. Char-wise operations are the most adversely affected as we might expect but, somewhat surprisingly, simple assignment of strings actually comes out as the most badly affected of the basic operations.<\/p>\n<p style=\"padding-left: 30px;\">3. ANSI string handling is generally as good as if not slightly better than Delphi 2007 overall, even more so when compared to Delphi 7.\u00a0 Notable exceptions to this remain in the form of the lack of an ANSI implementation for <strong>IntToStr()<\/strong> and a significantly slower <strong>Replace()<\/strong> implementation.<\/p>\n<p style=\"padding-left: 30px;\">4. There is still a question mark over the raison d&#8217;etre of TStringBuilder, although the difference in performance &#8211; whilst still very dramatic &#8211; is not perhaps as great as first it appeared.<\/p>\n<h2>Revised Conclusion<\/h2>\n<p>Concerns w.r.t the performance of ANSI strings were largely misplaced.<\/p>\n<p>There remain a couple of potential gotcha&#8217;s in the form of <strong>IntToStr()<\/strong> and <strong>Replace()<\/strong> but as previously noted, the <strong>FastReplace()<\/strong> implementation remains the gold standard for anyone concerned enough to use it (after taking care to ANSI-fy the API of FastStrings itself of course).<\/p>\n<p>Overall string handling performance at worst undoes some of the gains made in this area in Delphi 2007, but I think that is a reasonable trade for the Unicode capabilities added as a result.<\/p>\n<p>I have also learned some valuable lessons that have improved the utility of my SmokeTest framework into the bargain, so thanks to all who questioned and probed the previous results.<\/p>\n","protected":false},"excerpt":{"rendered":"<p><span class=\"rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">[Estimated Reading Time: <\/span> <span class=\"rt-time\">3<\/span> <span class=\"rt-label rt-postfix\">minutes]<\/span><\/span> It looks like I may have jumped the gun with my conclusions from the previous exercise to benchmark string performance in Delphi 2009.\u00a0 Following a useful exchange in the comments with Kryvich I corrected a small discrepancy in the tests and made some changes to the performance testing subsystem within the SmokeTest framework.\u00a0 I then [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":[]},"categories":[4,7],"tags":[64,61,292,60,293,22,65],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p1TKYv-63","jetpack_sharing_enabled":true,"jetpack-related-posts":[{"id":349,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/349\/","url_meta":{"origin":375,"position":0},"title":"Delphi 2009 &#8211; String Performance","date":"18 Sep 2008","format":false,"excerpt":"NOTE: Downloads are now fixed! Andreas Hausladen generously took the time to make some detailed comments on my previous post, one of which prompted me to throw together some further performance test cases for String types specifically.\u00a0 The results were something of a mixed bag and contained some surprises. The\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.deltics.co.nz\/blog\/wp-content\/uploads\/delphi2009-stringperformance-resultscapture.jpg?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]},{"id":2185,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/2185\/","url_meta":{"origin":375,"position":1},"title":"Smoketest &#8211; Performance Case Visualisations","date":"22 Nov 2013","format":false,"excerpt":"This post is a peek behind the curtain of the next major update to Smoketest which I hope to have completed shortly: Performance Case visualisations. Smoketest has always had two types of test case that you could implement by deriving from two distinct base classes: TTestCase is the base class\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.deltics.co.nz\/blog\/wp-content\/uploads\/Screen-Shot-2013-11-22-at-09.57.52.png?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]},{"id":284,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/284\/","url_meta":{"origin":375,"position":2},"title":"This Week&#8217;s Poll, Delphi at Tech Ed and 2009 Ship Date","date":"01 Sep 2008","format":false,"excerpt":"Since I'm preparing a series of posts about (and eventual publication of) Smoketest, my own testing framework, I thought I'd test the water with this weeks poll and see what - if anything - people are already using as far as unit testing goes. Also I thought I'd briefly mention\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":2006,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/2006\/","url_meta":{"origin":375,"position":3},"title":"Blowing Smoke&#8230;","date":"01 Nov 2013","format":false,"excerpt":"To alleviate the grind of polishing and sanitising my code (and, let's be honest, just plain 'fixing' it in some cases) ready for release, I have re-kindled my participation on Stack Overflow. In a happy confluence yesterday a question came up which allowed me to exercise one of the libraries\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"Ready to Run","src":"https:\/\/i0.wp.com\/www.deltics.co.nz\/blog\/wp-content\/uploads\/Screen-Shot-2013-11-01-at-09.00.33.png?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]},{"id":2144,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/2144\/","url_meta":{"origin":375,"position":4},"title":"Smoketest 1.0 &#8211; Release and Be Damned!","date":"14 Nov 2013","format":false,"excerpt":"As I have been promising for some time (quite literally 5 years (!), I am ashamed to admit) I am finally unclenching and releasing the Smoketest framework into the wild, ready or not. The code is published and will continue to be updated in a github repository. Documentation is still\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.deltics.co.nz\/blog\/wp-content\/uploads\/Screen-Shot-2013-11-14-at-19.51.57-.png?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]},{"id":2111,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/2111\/","url_meta":{"origin":375,"position":5},"title":"Extending Smoketest (Part 2) &#8211; Great(er) Expectations","date":"07 Nov 2013","format":false,"excerpt":"In my previous post on Smoketest I showed how you can extend the inspections framework to work with complex types in your code. As promised, I shall now show how you can do much the same thing to extend the framework with entirely new tests. \u201cI must be taken as\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"_links":{"self":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/375"}],"collection":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/comments?post=375"}],"version-history":[{"count":11,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/375\/revisions"}],"predecessor-version":[{"id":478,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/375\/revisions\/478"}],"wp:attachment":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/media?parent=375"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/categories?post=375"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/tags?post=375"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}