[fpc-pascal] ShortString still relevant today?
Guillermo Martínez Jiménez
gmartinez at burdjia.com
Tue Jul 4 17:59:52 CEST 2023
Hi,
I'm not sure but I think that CPU caches (L1, L2...) have some impact
on this example. Also I think PChar assignation should use string
copy instead (Strings.strcopy). Not time to do my own tests right now
though u_u) .
Regards,
Guillermo "Ñuño" Martínez
El Tue, 4 Jul 2023 11:46:42 +0700
Hairy Pixels via fpc-pascal <fpc-pascal at lists.freepascal.org> escribió:
> Here is my test unit I'm playing with. It's crude but can anyone
> suggest what other things I could test?
>
> I'm playing with a string pointer also to see how ref
> counting/finalization plays in. Making your own managed typed using
> management operators is not tested but I'm sure it will be terrible
> compared to everything else.
>
> * test_short_string time: 143ms
> * test_ansi_string time: 115ms
> * test_mem_string time: 115ms
>
> * test_short_string_record time: 165ms
> * test_ansi_string_record time: 75ms
> * test_mem_string_record time: 47ms
>
> * test_short_string_mutate time: 203ms
> * test_ansi_string_mutate time: 181ms
>
> =======================================================================================
>
> {$mode objfpc}
>
> program string_test;
> uses
> SysUtils, DateUtils;
>
> const
> ITERATIONS = 1000 * 1000;
> TEST_STRING = 'Lorem ipsum dolor sit amet, consectetur adipiscing
> elit';
>
> type
> TTestProc = procedure;
>
> procedure test_mem_string;
>
> procedure do_pass(const s: PString; len: Integer);
> var
> c: Char;
> i: Integer;
> begin
> for i := 0 to len - 1 do
> c := s^[i];
> end;
>
> var
> s: PString;
> i, len: Integer;
> begin
> for i := 0 to ITERATIONS - 1 do
> begin
> len := Length(TEST_STRING);
> s := GetMem(len);
> s^ := TEST_STRING;
> do_pass(s, len);
> FreeMem(s);
> end;
> end;
>
> procedure test_short_string;
>
> procedure do_pass(const s: ShortString);
> var
> c: Char;
> i: Integer;
> begin
> for i := 0 to length(s) - 1 do
> c := s[i];
> end;
>
> var
> s: Shortstring;
> i: Integer;
> begin
> for i := 0 to ITERATIONS - 1 do
> begin
> s := TEST_STRING;
> do_pass(s);
> end;
> end;
>
> procedure test_ansi_string;
>
> procedure ansi_string_pass(const s: AnsiString);
> var
> c: Char;
> i: Integer;
> begin
> for i := 0 to length(s) - 1 do
> c := s[i];
> end;
>
> var
> s: AnsiString;
> i: Integer;
> begin
> for i := 0 to ITERATIONS - 1 do
> begin
> s := TEST_STRING;
> ansi_string_pass(s);
> end;
> end;
>
> procedure test_ansi_string_mutate;
> var
> i, j: Integer;
> s1, s2: AnsiString;
> begin
> for i := 0 to ITERATIONS - 1 do
> begin
> s1 := TEST_STRING;
> s2 := s1 + IntToStr(i);
> for j := 1 to length(s2) - 1 do
> s2[j] := 'x';
> end;
> end;
>
> procedure test_short_string_mutate;
> var
> i, j: Integer;
> s1, s2: ShortString;
> begin
> for i := 0 to ITERATIONS - 1 do
> begin
> s1 := TEST_STRING;
> s2 := s1 + IntToStr(i);
> for j := 1 to length(s2) - 1 do
> s2[j] := 'x';
> end;
> end;
>
> procedure test_short_string_record;
>
> type
> TMyRecord = record
> a: ShortString;
> b: ShortString;
> c: ShortString;
> end;
>
> function do_pass(rec: TMyRecord): TMyRecord;
> begin
> result := rec;
> end;
>
> var
> i: Integer;
> r: TMyRecord;
> begin
> for i := 0 to ITERATIONS - 1 do
> begin
> r.a := TEST_STRING;
> r.b := TEST_STRING;
> r.c := TEST_STRING;
> do_pass(r);
> end;
> end;
>
>
> procedure test_ansi_string_record;
>
> type
> TMyRecord = record
> a: AnsiString;
> b: AnsiString;
> c: AnsiString;
> end;
>
> function do_pass(rec: TMyRecord): TMyRecord;
> begin
> result := rec;
> end;
>
> var
> i: Integer;
> r: TMyRecord;
> begin
> for i := 0 to ITERATIONS - 1 do
> begin
> r.a := TEST_STRING;
> r.b := TEST_STRING;
> r.c := TEST_STRING;
>
> do_pass(r);
> end;
> end;
>
> procedure test_mem_string_record;
>
> type
> TMyRecord = record
> a: PString;
> b: PString;
> c: PString;
> end;
>
> function do_pass(rec: TMyRecord): TMyRecord;
> begin
> result := rec;
> end;
>
> var
> i: Integer;
> r: TMyRecord;
> len: Integer;
> begin
> len := Length(TEST_STRING);
>
> for i := 0 to ITERATIONS - 1 do
> begin
> r.a := GetMem(len);
> r.b := GetMem(len);
> r.c := GetMem(len);
>
> r.a^ := TEST_STRING;
> r.b^ := TEST_STRING;
> r.c^ := TEST_STRING;
>
> do_pass(r);
> end;
> end;
>
>
> procedure run_test(name: String; test: TTestProc);
> var
> startTime: Double;
> begin
> startTime := Now;
> test;
> writeln('* ', name,' time: ', MilliSecondsBetween(Now, StartTime),
> 'ms'); end;
>
> begin
> run_test('test_short_string', @test_short_string);
> run_test('test_ansi_string', @test_ansi_string);
> run_test('test_mem_string', @test_ansi_string);
>
> run_test('test_short_string_record', @test_short_string_record);
> run_test('test_ansi_string_record', @test_ansi_string_record);
> run_test('test_mem_string_record', @test_mem_string_record);
>
> run_test('test_short_string_mutate', @test_short_string_mutate);
> run_test('test_ansi_string_mutate', @test_ansi_string_mutate);
> end.
>
> Regards,
> Ryan Joseph
>
> _______________________________________________
> fpc-pascal maillist - fpc-pascal at lists.freepascal.org
> https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
More information about the fpc-pascal
mailing list