Difference between Delphi compilers between IntToStr () and Integer.ToString ()?

What is the main difference between IntToStr() and Integer.ToString() when converting Integer to string . Which one is faster?

 var VarInt: integer; VarStr: string; begin VarInt := 5; VarStr := IntToStr(VarInt); VarStr := VarInt.ToString; end; 
+4
delphi delphi-xe delphi-10.2-tokyo
source share
2 answers

Disclaimer: The following text contains information that applies only to Delphi 10.2.1 (as well as 10.2.2), which seem to have done something worse in inlining and RVO:

The code generated by the compiler is really different (regardless of the version of the compiler), as you can easily see when viewing the disassembly window.

Take this procedure:

 procedure Main; var i: Integer; s: string; begin i := 0; s := IntToStr(i); s := i.ToString; end; 

Now run this and look at the disassembly window to check the code generated by the compiler:

This is what you got with Delphi 10.1:

 Project1.dpr.14: s := IntToStr(i); 00419810 8D55F8 lea edx,[ebp-$08] 00419813 8B45FC mov eax,[ebp-$04] 00419816 E80DA4FFFF call IntToStr Project1.dpr.15: s := i.ToString; 0041981B 8D55F4 lea edx,[ebp-$0c] 0041981E 8B45FC mov eax,[ebp-$04] 00419821 E802A4FFFF call IntToStr 00419826 8D45F8 lea eax,[ebp-$08] 00419829 8B55F4 mov edx,[ebp-$0c] 0041982C E843D2FEFF call @UStrLAsg 

And this is what you get with 10.2.1 (as well as 10.2.2):

 Project1.dpr.14: s := IntToStr(i); 00419B04 8D55F8 lea edx,[ebp-$08] 00419B07 8B45FC mov eax,[ebp-$04] 00419B0A E8C5A2FFFF call IntToStr Project1.dpr.15: s := i.ToString; 00419B0F 33C0 xor eax,eax 00419B11 55 push ebp 00419B12 68499B4100 push $00419b49 00419B17 64FF30 push dword ptr fs:[eax] 00419B1A 648920 mov fs:[eax],esp 00419B1D 8D55F4 lea edx,[ebp-$0c] 00419B20 8B45FC mov eax,[ebp-$04] 00419B23 E8ACA2FFFF call IntToStr 00419B28 8D45F8 lea eax,[ebp-$08] 00419B2B 8B55F4 mov edx,[ebp-$0c] 00419B2E E805D0FEFF call @UStrLAsg 00419B33 33C0 xor eax,eax 00419B35 5A pop edx 00419B36 59 pop ecx 00419B37 59 pop ecx 00419B38 648910 mov fs:[eax],edx 00419B3B 68509B4100 push $00419b50 00419B40 8D45F4 lea eax,[ebp-$0c] 00419B43 E8D4CCFEFF call @UStrClr 00419B48 C3 ret 00419B49 E9CEC3FEFF jmp @HandleFinally 00419B4E EBF0 jmp $00419b40 

Now a million dollar question, what kind of additional instructions are there ?!

Additional instructions that you can see in both compilers are the result of the lack of so-called return value optimization. As you know, the compiler treats the results of functions that have a managed type (for example, string) as a hidden var parameter. Now, when the compiler makes an attachment, it does not eliminate this parameter and directly passes the variable s to IntToStr , as it happens with a direct call. Rather, it reserves the temporary variable that it uses to go to IntToStr , and then after that assigns this variable s (that call @UStrLAsg you see 3 lines there after calling IntToStr ).

As I mentioned above, in 10.2 or 10.2.1 there is a regression where they changed something about temporarily clearing variables immediately after the built-in call (which is additional instructions before and after).

Marked as RSP-19439 .

To be continued...

+9
source share

There is no difference.

Int.ToString defined as follows:

 function TIntHelper.ToString: string; inline; begin Result := IntToStr(Self); end; 

Since it is built-in, it simply converts to IntToStr(Int) .

var.action methods have been added to make the Runtime Library (RTL) more welcoming for Java and C # programmers. This is especially true for mobile platforms where people are likely to be exposed to Java.

The main advantage of this is that the functions are much more searchable. You can just enter VarInt. , and autocomplete will show you all the available options. If you do not know about IntToStr , then it is already difficult to find it.

+3
source share

All Articles