Optimization of TextToFloat
Summary
The function TextToFloat()
is the internal basis of the String-to-Float conversions of FPC, such as StrToFloat
or TryStrToFloat
. The function can be optimized at two places:
- At the beginning of the routine there is a conversion from PChar to string which in most cases is not necessary because the argument passed to
StrToFloat
,TryStrToFloat
etc. already is a string. (#1) - There are three calls to
pos()
in order to correctly handle the decimal and thousand separators. At least the last one which replaces the decimal separator in the string by a dot can be omitted if the FormatSettings.DecimalSeparator already is a dot. (#2)
Here is the original code:
Function TextToFloat(Buffer: PChar; Out Value: Extended; Const FormatSettings: TFormatSettings): Boolean;
Var
S : String;
...
Begin
S:=StrPas(Buffer); // #1
...
P:=Pos(FormatSettings.DecimalSeparator,S); // #2
If (P<>0) Then
S[P] := '.';
System Information
- Operating system: Win-11 (64 bit)
- Processor architecture: x86-64
- Compiler version: FPC/main (e01da240)
- Device: Computer
Fix
The attached patch fixes the issue:
#1: It moves the current code of TextToFloat()
(there are two overloaded variants) into new procedures InternalTextToFloat()
having a string argument rather than the PChar as in the old code. The call to StrPas(Buffer)
, therefore, can be removed. In order to maintain compatibility of the interface, TextToFloat()
is kept with the PChar argument, but it just calls InternalTextToFloat
after doing the conversion to string here.
#2: The unnecessary call to pos()
is avoided by putting this code into an if FormatSettings.DecimalSeparator <> '.'
block.
A test project is added which verifies that nothing breaks with these changes. It also includes a simple speed test which demonstrates that the patch results in a 20% speed improvement (when the decimal separator is a point).
- execution time before: 1.21 seconds
- execution time after: 0.97 seconds, i.e. 20% faster.