C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
분야별 포럼
C++빌더
델파이
파이어몽키
C/C++
프리파스칼
파이어버드
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

자유게시판
세상 살아가는 이야기들을 나누는 사랑방입니다.
[15687] [펌] Performance tip: Length(String) and Str[Index] in Delphi 2009
유비쿼터스 [janux] 5733 읽음    2009-02-13 22:21
* 참고삼아...........

출처 : 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
이경문 [gilgil]   2009-02-13 22:32 X
음... 이런 슬픈 현실이... 아직 2009를 사용하지 않아서 잘 모르겠지만, 아무튼 좋은 정보 감사합니다. ^^

+ -

관련 글 리스트
15687 [펌] Performance tip: Length(String) and Str[Index] in Delphi 2009 유비쿼터스 5733 2009/02/13
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.