program project1; {$mode objfpc}{$H+} uses Classes, DateUtils, SysUtils, StrBuf; type TBench = procedure(const PartSize, MaxSize: Integer); procedure BuildString(const PartSize, MaxSize: Integer); var Buf: String; BufSize: Integer; begin Buf := ''; BufSize := 0; while BufSize < MaxSize do begin Buf += StringOfChar(' ', PartSize); BufSize += PartSize; end; end; procedure BuildStringList(const PartSize, MaxSize: Integer); var Buf: TStringList; BufSize: Integer; begin Buf := TStringList.Create; BufSize := 0; while BufSize < MaxSize do begin Buf.Add(StringOfChar(' ', PartSize)); BufSize += PartSize; end; Buf.Free; end; procedure BuildStrBuf(const PartSize, MaxSize: Integer); var Buf: TStrBuf; BufSize: Integer; begin BufSize := 0; while BufSize < MaxSize do begin Buf.W(StringOfChar(' ', PartSize)); BufSize += PartSize; end; end; procedure Build(const PartSize, MaxSize: Integer; Bench: TBench; const Name: String); const RUN = 5; var T0: TDateTime; Msec: Int64; I: Integer; begin T0 := Now; for I := 1 to RUN do Bench(PartSize, MaxSize); MSec := MilliSecondsBetween(Now, T0); Writeln(Format('partsize: %.5d T: %.7dms %s ', [PartSize, MSec, Name])); end; const UBOUND_PART = 100; UBOUND_BUF = 1000000; var PartSize: Integer; begin PartSize := 1; repeat Build(PartSize, UBOUND_BUF, @BuildString, 'String'); Build(PartSize, UBOUND_BUF, @BuildStringList, 'StringList'); Build(PartSize, UBOUND_BUF, @BuildStrBuf, 'StrBuf'); PartSize := ((3 * PartSize) + 1) div 2; until PartSize > UBOUND_PART; end.
$ fpc -B ./project1 && ./project1 | sort Free Pascal Compiler version 2.5.1 [2010/02/07] for x86_64 Copyright (c) 1993-2009 by Florian Klaempfl Target OS: Linux for x86-64 Compiling ./project1.pas Compiling strbuf.pas Linking project1 /usr/bin/ld: warning: link.res contains output sections; did you forget -T? 189 lines compiled, 0.2 sec partsize: 00001 T: 0000446ms StrBuf partsize: 00001 T: 0000602ms String partsize: 00001 T: 0001150ms StringList partsize: 00002 T: 0000233ms StrBuf partsize: 00002 T: 0000261ms String partsize: 00002 T: 0000534ms StringList partsize: 00003 T: 0000159ms StrBuf partsize: 00003 T: 0000190ms String partsize: 00003 T: 0000379ms StringList partsize: 00005 T: 0000101ms StrBuf partsize: 00005 T: 0000127ms String partsize: 00005 T: 0000211ms StringList partsize: 00008 T: 0000076ms StrBuf partsize: 00008 T: 0000086ms String partsize: 00008 T: 0000167ms StringList partsize: 00012 T: 0000050ms StrBuf partsize: 00012 T: 0000060ms String partsize: 00012 T: 0000100ms StringList partsize: 00018 T: 0000038ms StrBuf partsize: 00018 T: 0000043ms String partsize: 00018 T: 0000069ms StringList partsize: 00027 T: 0000030ms StrBuf partsize: 00027 T: 0000033ms String partsize: 00027 T: 0000045ms StringList partsize: 00041 T: 0000023ms String partsize: 00041 T: 0000024ms StrBuf partsize: 00041 T: 0000034ms StringList partsize: 00062 T: 0000015ms StrBuf partsize: 00062 T: 0000020ms String partsize: 00062 T: 0000020ms StringList partsize: 00093 T: 0000014ms String partsize: 00093 T: 0000015ms StringList partsize: 00093 T: 0000017ms StrBuf $
StrBuf's performance looks good or better compared to TStringList and/or String concatenating while you're appending short pieces of text, say up to few dozens of characters and that's what it was intended and written for.