Wednesday, February 10, 2010

String Buffer Performance

Benchmarks for the yesterday's post.

 
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.

No comments:

Post a Comment