* 참고삼아...........
출처 :
http://andy.jgknet.de/blog/?p=487
If you need performance in Delphi 2009 and you must keep the code compatible with C++Builder then don’t use Length(String) or Str[Index] in a loop. This has to do with the fact that Delphi 2009 bloats your code with the StringChecks code. The generated code looks so ugly and is so slow that CodeGear forces me to use PChar[Index-1] instead of Str[Index]. If the compiler would have been that smart that it would only convert the AnsiString in disguise to an UnicodeString once at the function start, but no, it has to do this for every single string access, be it writing to or reading from it. I understand why this is necessary, especially if you have events in between your code that might call into C++Builder code.
But I think a migration tool for the C++Builder users would have been much better than killing Delphi’s string performance and increasing the EXE/DLL/BPL size with such (for Delphi developers) useless code.
* Delphi 2007 generates 13 bytes for Length(String), Delphi 2009 generates 40 bytes (including on additional conditional jump that is executed for normal UnicodeStrings) for the exact same code. That’s 307% code increase for every use of Length(String)
* Delphi 2007 generates 5 bytes (no jump) for Str[1], Delphi 2009 generates 34 bytes (including a conditional jump that only is used for AnsiStrings in disguise) for the exact same code. That’s 680% code increase for every use of Str[I].
And now wonder why executable that are compiled with Delphi 2009 are larger than compile with Delphi 2007. And why iterating over a string accessing Str[Index] is much slower than using a PChar.
If you do not need to support C++Builder (generating *.hpp and *.obj files) then feel free to turn the {$STRINGCHECKS ON/OFF} switch OFF.
The following code:
function InStr(const S: string; Ch: Char): Integer;
begin
for Result := 1 to Length(S) do
if S[Result] = Ch then
Exit;
Result := 0;
end;
Compiled with Delphi 2007:
Unit1.pas.70: begin
004A78DC 56 push esi
Unit1.pas.71: for Result := 1 to Length(S) do
004A78DD 8BC8 mov ecx,eax
004A78DF 85C9 test ecx,ecx
004A78E1 7405 jz $004a78e8
004A78E3 83E904 sub ecx,$04
004A78E6 8B09 mov ecx,[ecx]
004A78E8 85C9 test ecx,ecx
004A78EA 7E0F jle $004a78fb
004A78EC BE01000000 mov esi,$00000001
Unit1.pas.72: if S[Result] = Ch then
004A78F1 3A5430FF cmp dl,[eax+esi-$01]
004A78F5 7406 jz $004a78fd
Unit1.pas.73: Exit;
004A78F7 46 inc esi
Unit1.pas.71: for Result := 1 to Length(S) do
004A78F8 49 dec ecx
004A78F9 75F6 jnz $004a78f1
Unit1.pas.74: Result := 0;
004A78FB 33F6 xor esi,esi
Unit1.pas.75: end;
004A78FD 8BC6 mov eax,esi
004A78FF 5E pop esi
004A7900 C3 ret
Compiled with Delphi 2009:
Unit1.pas.105: begin
00461E24 55 push ebp
00461E25 8BEC mov ebp,esp
00461E27 51 push ecx
00461E28 53 push ebx
00461E29 56 push esi
00461E2A 57 push edi
00461E2B 8BFA mov edi,edx
00461E2D 8945FC mov [ebp-$04],eax
00461E30 8B45FC mov eax,[ebp-$04]
00461E33 E8B035FAFF call @UStrAddRef
00461E38 33C0 xor eax,eax
00461E3A 55 push ebp
00461E3B 68B71E4600 push $00461eb7
00461E40 64FF30 push dword ptr fs:[eax]
00461E43 648920 mov fs:[eax],esp
Unit1.pas.106: for Result := 1 to Length(S) do
00461E46 8B45FC mov eax,[ebp-$04]
00461E49 85C0 test eax,eax
00461E4B 7416 jz $00461e63
00461E4D 8BD0 mov edx,eax
00461E4F 83EA0A sub edx,$0a
00461E52 66833A02 cmp word ptr [edx],$02
00461E56 740B jz $00461e63
00461E58 8D45FC lea eax,[ebp-$04]
00461E5B 8B55FC mov edx,[ebp-$04]
00461E5E E8A12FFAFF call @InternalUStrFromLStr
00461E63 85C0 test eax,eax
00461E65 7405 jz $00461e6c
00461E67 83E804 sub eax,$04
00461E6A 8B00 mov eax,[eax]
00461E6C 8BD8 mov ebx,eax
00461E6E 85DB test ebx,ebx
00461E70 7E2D jle $00461e9f
00461E72 BE01000000 mov esi,$00000001
Unit1.pas.107: if S[Result] = Ch then
00461E77 8B45FC mov eax,[ebp-$04]
00461E7A 85C0 test eax,eax
00461E7C 7416 jz $00461e94
00461E7E 8BD0 mov edx,eax
00461E80 83EA0A sub edx,$0a
00461E83 66833A02 cmp word ptr [edx],$02
00461E87 740B jz $00461e94
00461E89 8D45FC lea eax,[ebp-$04]
00461E8C 8B55FC mov edx,[ebp-$04]
00461E8F E8702FFAFF call @InternalUStrFromLStr
00461E94 663B7C70FE cmp di,[eax+esi*2-$02]
00461E99 7406 jz $00461ea1
Unit1.pas.108: Exit;
00461E9B 46 inc esi
Unit1.pas.106: for Result := 1 to Length(S) do
00461E9C 4B dec ebx
00461E9D 75D8 jnz $00461e77
Unit1.pas.109: Result := 0;
00461E9F 33F6 xor esi,esi
Unit1.pas.110: end;
00461EA1 33C0 xor eax,eax
00461EA3 5A pop edx
00461EA4 59 pop ecx
00461EA5 59 pop ecx
00461EA6 648910 mov fs:[eax],edx
00461EA9 68BE1E4600 push $00461ebe
00461EAE 8D45FC lea eax,[ebp-$04]
00461EB1 E83A35FAFF call @UStrClr
00461EB6 C3 ret
00461EB7 E9FC24FAFF jmp @HandleFinally
00461EBC EBF0 jmp $00461eae
00461EBE 8BC6 mov eax,esi
00461EC0 5F pop edi
00461EC1 5E pop esi
00461EC2 5B pop ebx
00461EC3 59 pop ecx
00461EC4 5D pop ebp
00461EC5 C3 ret