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/
http://www.delphitools.info/2013/10/28/efficient-string-concatenation-in-delphi/
What an excellent tip, great post.
ReplyDeleteWell I suppose that works great for single concatenations. But it still looks like Schlemiel the painter's algorithm to me.
ReplyDeleteOliver 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 ;-) )
ReplyDeleteActually, 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.
ReplyDeletePaul Foster You've got to benchmark. It's very easy to break conceptually good ideas with poor implementations (TStringBuilder, I'm looking at you).
ReplyDeleteMy guess is we'll see immutable strings accompanied by an updated TStringBuilder to handle the grunt work.
ReplyDeleteEric Grange come on, be specific - what's your complaint about stringbuilder? (I have a good idea, but others might not)
ReplyDeleteI've found that doing
ReplyDeleteSetLength(Result, ) ;
Result := '';
before doing multiple concatenations also makes a huge difference.
In which Delphi version?
ReplyDeleteLars 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
ReplyDeleteIt 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.
ReplyDeleteLars 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.
ReplyDeleteThe 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)
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.
ReplyDeleteI 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.
Lars Fosdal yeah, because you allocate all you need in one system call, no need for multi malloc and free.
ReplyDeleteBtw. 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 (:
Yes, if you don't reduce the length to zero, it really preallocates a large buffer.
ReplyDeleteDorin Duminica That would be overkill. The HTML pages are mostly used for diagnostics and logs.
ReplyDeleteLars Fosdal aw, in that case yeah (:
ReplyDeleteGraeme 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
ReplyDeleteFWIW, my old WebBroker on Steroids code (CodeCentral) contains a TStringData class that is optimized for building large strings from smaller segments.
ReplyDelete