Recent

Author Topic: Any TStringBuilder class implementation?  (Read 24696 times)

bytebites

  • Hero Member
  • *****
  • Posts: 776
Re: Any TStringBuilder class implementation?
« Reply #45 on: January 11, 2026, 04:46:22 pm »
Sb should win always.

Code: Pascal  [Select][+][-]
  1. program app;
  2. {$mode objfpc}{$h+}
  3.  
  4. uses SysUtils, DateUtils;
  5.  
  6. const
  7.   c = 10000000;
  8.  
  9. var
  10.   sb: TStringBuilder;
  11.   t: TDateTime;
  12.   i: Integer;
  13.   r: AnsiString;
  14.  
  15. begin
  16.   t:=Now;
  17.   r:='';
  18.   for i:=1 to c do
  19.       r:=r+AnsiString('e');
  20.  
  21.   WriteLn('concat: ', MilliSecondsBetween(Now, t));
  22.  
  23.   t:=Now;
  24.   sb:=TStringBuilder.Create; // default capacity used
  25.   for i:=1 to c do
  26.       sb.Append(AnsiString('e'));
  27.   WriteLn('sb default: ', MilliSecondsBetween(Now, t));
  28.   sb.Free;
  29.  
  30.   t:=Now;
  31.   sb:=TStringBuilder.Create(c);
  32.   for i:=1 to c do
  33.       sb.Append(AnsiString('e'));
  34.   WriteLn('sb: no realloc ', MilliSecondsBetween(Now, t));
  35.   sb.Free;
  36. end.

And that's how it is )

Code: Pascal  [Select][+][-]
  1. concat: 406
  2. sb default: 118
  3. sb: no realloc 112

LOL! Issue is about append char without any gimmicks.
« Last Edit: January 11, 2026, 04:52:20 pm by bytebites »

BeniBela

  • Hero Member
  • *****
  • Posts: 955
    • homepage
Re: Any TStringBuilder class implementation?
« Reply #46 on: January 11, 2026, 04:47:44 pm »
that is all bad

Code: Pascal  [Select][+][-]
  1. program app;
  2.  
  3. {$mode objfpc}{$h+}
  4.  
  5. uses SysUtils, DateUtils,bbutils;
  6.  
  7. const
  8.   c = 10000000;
  9.  
  10. var
  11.   sb: TStringBuilder;
  12.   t: TDateTime;
  13.   i: Integer;
  14.   r, r2: AnsiString;
  15.   mysb: TStrBuilder;
  16. begin
  17.   t:=Now;
  18.   r:='';
  19.   for i:=1 to c do
  20.       r:=r+'e';
  21.  
  22.   WriteLn('concat: ', MilliSecondsBetween(Now, t));
  23.  
  24.   t:=Now;
  25.   sb:=TStringBuilder.Create; // default capacity used
  26.   for i:=1 to c do
  27.       sb.Append('e');
  28.   WriteLn('sb default: ', MilliSecondsBetween(Now, t));
  29.   sb.Free;
  30.  
  31.   t:=Now;
  32.   sb:=TStringBuilder.Create(c);
  33.   for i:=1 to c do
  34.       sb.Append('e');
  35.   WriteLn('sb: no realloc ', MilliSecondsBetween(Now, t));
  36.   sb.Free;
  37.  
  38.   t:=Now;
  39.   mysb.init(@r2);
  40.   for i:=1 to c do
  41.       mysb.Append('e');
  42.   mysb.final;
  43.   WriteLn('mysb: default ', MilliSecondsBetween(Now, t));
  44.  
  45.   t:=Now;
  46.   mysb.init(@r2, length(r2));
  47.   for i:=1 to c do
  48.       mysb.Append('e');
  49.   mysb.final;
  50.   WriteLn('mysb: no realloc ', MilliSecondsBetween(Now, t));
  51.   readln;
  52. end.


Code: [Select]
concat: 735
sb default: 546
sb: no realloc 533
mysb: default 33
mysb: no realloc 18
« Last Edit: January 11, 2026, 04:50:51 pm by BeniBela »

ALLIGATOR

  • Sr. Member
  • ****
  • Posts: 370
  • I use FPC [main] 💪🐯💪
Re: Any TStringBuilder class implementation?
« Reply #47 on: January 11, 2026, 04:58:12 pm »
LOL! Issue is about append char without any gimmicks.

That's your imagination. And a misunderstanding of how StringBuilder works and is structured internally
I may seem rude - please don't take it personally

bytebites

  • Hero Member
  • *****
  • Posts: 776
Re: Any TStringBuilder class implementation?
« Reply #48 on: January 11, 2026, 05:16:29 pm »
LOL! Issue is about append char without any gimmicks.

That's your imagination. And a misunderstanding of how StringBuilder works and is structured internally

Then tell correct understanding.

ALLIGATOR

  • Sr. Member
  • ****
  • Posts: 370
  • I use FPC [main] 💪🐯💪
Re: Any TStringBuilder class implementation?
« Reply #49 on: January 11, 2026, 05:19:36 pm »
that is all bad

Have you considered porting some improvements to RTL FPC?

I think that improving RTL benefits everyone, rather than having some improvements in a separate repository that few people know about, especially beginners (who, by the way, may draw the wrong conclusions about the capabilities of FPC/Lazarus and Pascal in general because of this)
I may seem rude - please don't take it personally

ALLIGATOR

  • Sr. Member
  • ****
  • Posts: 370
  • I use FPC [main] 💪🐯💪
Re: Any TStringBuilder class implementation?
« Reply #50 on: January 11, 2026, 05:28:34 pm »
Then tell correct understanding.

SB is always faster

Look at the debugger and explain to yourself why you get such results with your examples

The thing is that char is converted to string every time, although... StringBuilder has an overloaded method for adding char

Why the necessary overload doesn't work is a separate issue

The SBChar type is used there, but it is private. If I could extract it to set the argument type to SB, your example would be faster

Just understand the reason. And that it has nothing to do with the general essence and idea of StringBuilder. As you can see from BeniBela's example, which also uses StringBuilder, but is even more optimized
I may seem rude - please don't take it personally

bytebites

  • Hero Member
  • *****
  • Posts: 776
Re: Any TStringBuilder class implementation?
« Reply #51 on: January 11, 2026, 08:36:14 pm »
Then tell correct understanding.

SB is always faster

Look at the debugger and explain to yourself why you get such results with your examples

The thing is that char is converted to string every time, although... StringBuilder has an overloaded method for adding char

Why the necessary overload doesn't work is a separate issue

The SBChar type is used there, but it is private. If I could extract it to set the argument type to SB, your example would be faster

Just understand the reason. And that it has nothing to do with the general essence and idea of StringBuilder. As you can see from BeniBela's example, which also uses StringBuilder, but is even more optimized

Your SBChar change does not help since doappend does not have overload for char type so char is always converted to string.
But adding overloaded function does not improve speed dramatically.

Code: Pascal  [Select][+][-]
  1. diff --git a/rtl/objpas/sysutils/syssb.inc b/rtl/objpas/sysutils/syssb.inc
  2. index b4f4c8d01a..8af76fc8cd 100644
  3. --- a/rtl/objpas/sysutils/syssb.inc
  4. +++ b/rtl/objpas/sysutils/syssb.inc
  5. @@ -117,6 +117,17 @@ procedure TGenericStringBuilder.CheckNegative(const AValue: Integer;
  6.  
  7.  {  These do the actual Appending/Inserting }
  8.  
  9. +procedure TGenericStringBuilder.DoAppend(ch : AnsiChar );
  10. +
  11. +Var
  12. +  L : Integer;
  13. +
  14. +begin
  15. +  L:=Length;
  16. +  Length:=L + 1;
  17. +  FData[L] := ch;
  18. +end;
  19. +
  20.  procedure TGenericStringBuilder.DoAppend(const S: {$IFDEF SBUNICODE}SBString{$ELSE}RawByteString{$ENDIF});
  21.  
  22.  Var
  23. diff --git a/rtl/objpas/sysutils/syssbh.inc b/rtl/objpas/sysutils/syssbh.inc
  24. index ceb296643b..eb09b32f05 100644
  25. --- a/rtl/objpas/sysutils/syssbh.inc
  26. +++ b/rtl/objpas/sysutils/syssbh.inc
  27. @@ -32,6 +32,7 @@       TCharEnumerator = record
  28.      Procedure CheckNegative(Const AValue : Integer; Const AName: SBString); inline;
  29.      // All appends/inserts pass through here.
  30.  
  31. +    Procedure DoAppend( ch: AnsiChar);virtual;
  32.      Procedure DoAppend(Const S : {$IFDEF SBUNICODE}SBString{$ELSE}RawByteString{$ENDIF});virtual;
  33.      Procedure DoAppend(const AValue: TSBCharArray; Idx, aCount: Integer); virtual;
  34.      Procedure DoInsert(Index: Integer; const AValue: SBString); virtual;
  35.  

Code: Pascal  [Select][+][-]
  1. program app;
  2. {$mode objfpc}{$h+}
  3.  
  4. uses SysUtils, DateUtils;
  5.  
  6. const
  7.   c = 10000000;
  8.  
  9. var
  10.   sb: TStringBuilder;
  11.   t: TDateTime;
  12.   i: Integer;
  13.   r: AnsiString;
  14.  
  15. begin
  16.   t:=Now;
  17.   r:='';
  18.   for i:=1 to c do
  19.       r:=r+chr(random(90)+1);
  20.  
  21.   WriteLn('concat: ', MilliSecondsBetween(Now, t));
  22.  
  23.   t:=Now;
  24.   sb:=TStringBuilder.Create; // default capacity used
  25.   for i:=1 to c do
  26.       //sb.Append(AnsiString('e'));
  27.       //sb.Append(AnsiString(chr(random(90)+1)));
  28.       sb.Append(chr(random(90)+1));
  29.   WriteLn('sb char: ', MilliSecondsBetween(Now, t));
  30.   sb.Free;
  31.  
  32.   t:=Now;
  33.   sb:=TStringBuilder.Create;
  34.   for i:=1 to c do
  35.       sb.Append(AnsiString(chr(random(90)+1)));
  36.   WriteLn('sb: string(char) ', MilliSecondsBetween(Now, t));
  37.   sb.Free;
  38. end.
  39.    
  40.  
Quote
concat: 290
sb char: 131
sb: string(char) 203

ALLIGATOR

  • Sr. Member
  • ****
  • Posts: 370
  • I use FPC [main] 💪🐯💪
Re: Any TStringBuilder class implementation?
« Reply #52 on: January 11, 2026, 08:56:17 pm »
Your SBChar change does not help since doappend does not have overload for char type so char is always converted to string.
But adding overloaded function does not improve speed dramatically.

Wow! Thank you for such an in-depth test 🆒

Yes, here you need to look into what's going on, somewhere there are hidden overhead costs

In general, it would be great to upgrade the built-in SB so that it is suitable for virtually all applications by default  ::)
I may seem rude - please don't take it personally

BeniBela

  • Hero Member
  • *****
  • Posts: 955
    • homepage
Re: Any TStringBuilder class implementation?
« Reply #53 on: January 11, 2026, 11:35:17 pm »
that is all bad

Have you considered porting some improvements to RTL FPC?

I think that improving RTL benefits everyone, rather than having some improvements in a separate repository that few people know about, especially beginners (who, by the way, may draw the wrong conclusions about the capabilities of FPC/Lazarus and Pascal in general because of this)

Changing it  would not be backwards compatible

The DoAppend method would need to be replaced, but people might have been using it

ALLIGATOR

  • Sr. Member
  • ****
  • Posts: 370
  • I use FPC [main] 💪🐯💪
Re: Any TStringBuilder class implementation?
« Reply #54 on: January 12, 2026, 04:07:30 am »
I wonder how FPC developers feel about creating a new stringbuilder unit with a new implementation of TStringBuilder and marking the old type as deprecated

Then the world would become a little better  :)
I may seem rude - please don't take it personally

 

TinyPortal © 2005-2018