Check if the destination contents are going to change.
In fpc_shortstr_to_ansistr
and fpc_char_to_ansistr
, check if (small enough, to limit bad cases) Result
already has the desired contents. This can have nontrivial probability for various reasons; e.g. benchmark SaBenchmark.pas calls IntToStr
in a loop because guess what.
My results:
before after
Same IntToStr (temporary): 20 ns/call 10 ns/call
Same IntToStr (global): 60 ns/call 12 ns/call
Worst case: 20 ns/call 24 ns/call
Compiling FPC+libraries with FpcUpDeluxe
hits this case in 2.7% (272k / 10m) of fpc_shortstr_to_ansistr
and 0.4% (658 / 174k) of fpc_char_to_ansistr
.
Compiling Lazarus with FpcUpDeluxe
: 2.8% (1.07m / 38.2m) of fpc_shortstr_to_ansistr
and 0.8% (3.7k / 449k) of fpc_char_to_ansistr
.
Running Lazarus: 12.4% (22k / 177k) of fpc_shortstr_to_ansistr
and 87% (30.4k / 35k) of fpc_char_to_ansistr
.
And no, concatenations are worse (might depend on the application, but my application, FPC, and Lazarus are all bad to terrible examples, thus appearing to be a trend; also, eg compiling FPC+libraries with FPCUpDeluxe calls fpc_pchar_to_ansistr
like a trillion (5 millions) of times and they run in 0.255 s with zero cases for result reuse, but adding the same optimization to fpc_pchar_to_ansistr
does not change their performance at all, even though 30% of these calls reach CompareByte
; so I think I will do the same for concatenations once I have a single use case :D; concatenation checks are more complex though, deteriorating the main branch more).