Simple trick that can improve both performance and debug-ability

Simple trick that can improve both performance and debug-ability
http://www.delphitools.info/2013/10/28/efficient-string-concatenation-in-delphi/

Comments

  1. What an excellent tip, great post.

    ReplyDelete
  2. Well I suppose that works great for single concatenations. But it still looks like  Schlemiel the painter's algorithm to me.

    ReplyDelete
  3. Oliver Holmes For small concatenations, you'll have a hard-time doing better without going all PChar or static arrays. For longer concatenations, what Delphi class would you pick? ( beware, this question is a trap ;-) )

    ReplyDelete
  4. Actually, in the new ARC world - what with immutable strings and all - what IS the best way of dealing with string concatenation?  It was bad enough with ansistrings TBH, never mind unicode ones.

    ReplyDelete
  5. Paul Foster You've got to benchmark. It's very easy to break conceptually good ideas with poor implementations (TStringBuilder, I'm looking at you).

    ReplyDelete
  6. My guess is we'll see immutable strings accompanied by an updated TStringBuilder to handle the grunt work.

    ReplyDelete
  7. Eric Grange come on, be specific - what's your complaint about stringbuilder? (I have a good idea, but others might not)

    ReplyDelete
  8. I've found that doing
      SetLength(Result, ) ;
      Result := '';
    before doing multiple concatenations also makes a huge difference.

    ReplyDelete
  9. Lars Fosdal yeah, you're asking for memory, then "free" it, but the memory manager doesn't just give it back to the OS, so, when you do your concatenations, the MM doesn't need to ask the OS for another X bytes, it just has it available, therefore it avoids many system calls

    ReplyDelete
  10. It keeps the biggest allocation until the string goes out of scope, and if you reuse it, you avoid a lot of reallocation operations, Dorin Duminica.

    ReplyDelete
  11. Lars Fosdal The Result:='' will set the pointer to nil, so it's losing the allocation, and what you save is through the pre-allocation from the OS as Dorin said. It would be different if you did a second SetLength() to a small, non null length.
    The speedup you achieve that way is contextual, and in multi-threaded apps, another thread could "hijack" your pre-allocated space (the thread will see faster allocation, but your concatenation wouldn't)

    ReplyDelete
  12. I had to go check the code, and I guess you are right.  I don't set it to '', but rather the initial HTML header value.
    I use this in a multithreaded response handler for a http server which builds simple HTML tables from SQL queries or internal data structures, and setting the length up front did wonders for the performance.

    ReplyDelete
  13. Lars Fosdal yeah, because you allocate all you need in one system call, no need for multi malloc and free.

    Btw. I'd recommend sending data as JSON rather than HTML table, using jQuery, you can build the table on the fly and also trees, of course, if necessary (:

    ReplyDelete
  14. Yes, if you don't reduce the length to zero, it really preallocates a large buffer.

    ReplyDelete
  15. Dorin Duminica That would be overkill.  The HTML pages are mostly used for diagnostics and logs.

    ReplyDelete
  16. Lars Fosdal aw, in that case yeah (:

    ReplyDelete
  17. Graeme Geldenhuys the compiler can only get you so far, if you need high performance, you usually need to get your hands dirty and even code in asm

    ReplyDelete
  18. FWIW, my old WebBroker on Steroids code (CodeCentral) contains a TStringData class that is optimized for building large strings from smaller segments.

    ReplyDelete

Post a Comment