STRINGCHECKS problem a unicode Delphi

vložil Radek Červinka 4. února 2010 00:32

Předpokládám, že je to všeobecně známo jelikož se to píše všude, ale přesto. V unicode verzích Delphi (tj. 2009 a 2010) je pro lepší kompatibilitu s C++ Builderem implementována možnost lepší detekce správnosti hodnoty typu string. Rovnou říkám, že se jednalo o přechodné období, protože v budoucích Delphi to již nebude, jak napsal Allen Bauer na svém blogu.

Připomínám, že přechod na unicode je největší skok v historii Delphi, podobné je snad jen Delphi 1 (16 bit) -> Delphi 2 (32 bit).

Ale zpět. Tuto kontrolu klidně můžete vypnout (což už určitě máte) v případě, že používáte jen Delphi a tímto krokem získáte určité malé zrychlení.

Options

Všimněte si dvou voleb: inline kodu a toho stringchecks.

Výsledky této volby si ukážeme v praxi. Pro jednoduchost si zopakujeme, že volba optimalizace za pomoci inline kódu je ekvivalentem {$INLINE xx} a řízení kontroly řetězců je {$STRINGCHECKS xx}. Defaultním nastavením je {$STRINGCHECKS ON} a {$INLINE ON} (tj. oboje zapnuté).

Mějme tedy tento program (ekvivalent originálního nastavení):

program Project1;

{$APPTYPE CONSOLE}
{$STRINGCHECKS ON} // ekvivalent nastavení v options
{$INLINE ON}  // ekvivalent nastavení v options
var
  s: string;
  i: Integer;
begin
  s:= 'delphi.cz';
  i := Length(s);
  writeln(i);
end.

V assembleru je to pak takto: všimněte si InternalUStrFromLStr, což je zbytek po inline funkce pro kontrolu stringu (viz poslední ukázka).

Project1.dpr.9: s:= 'delphi.cz';
004050D7 B8389B4000       mov eax,$00409b38
004050DC BA54514000       mov edx,$00405154
004050E1 E81EEFFFFF       call @UStrAsg
Project1.dpr.10: i := Length(s);
004050E6 A1389B4000       mov eax,[$00409b38]
004050EB 85C0             test eax,eax
004050ED 741B             jz $0040510a
004050EF 8BD0             mov edx,eax
004050F1 83EA0A           sub edx,$0a
004050F4 66833A02         cmp word ptr [edx],$02
004050F8 7410             jz $0040510a
004050FA B8389B4000       mov eax,$00409b38
004050FF 8B15389B4000     mov edx,[$00409b38]
00405105 E8BAEEFFFF       call @InternalUStrFromLStr
0040510A 85C0             test eax,eax
0040510C 7405             jz $00405113
0040510E 83E804           sub eax,$04
00405111 8B00             mov eax,[eax]
00405113 8BD8             mov ebx,eax
Project1.dpr.11: writeln(i);
00405115 A1AC674000       mov eax,[$004067ac]

Nyní kontrolu vypneme - ideální stav, doporučeno.

program Project1;

{$APPTYPE CONSOLE}
{$STRINGCHECKS OFF} // ekvivalent nastavení v options
{$INLINE ON} // ekvivalent nastavení v options
var
  s: string;
  i: Integer;
begin
  s:= 'delphi.cz';
  i := Length(s);
  writeln(i);
end.

Výsledný kód je mnohem optimálnější, žádné zbytečné volání:

Project1.dpr.10: s:= 'delphi.cz';
004050D7 B8389B4000       mov eax,$00409b38
004050DC BA34514000       mov edx,$00405134
004050E1 E80EEFFFFF       call @UStrAsg
Project1.dpr.11: i := Length(s);
004050E6 A1389B4000       mov eax,[$00409b38]
004050EB 85C0             test eax,eax
004050ED 7405             jz $004050f4
004050EF 83E804           sub eax,$04
004050F2 8B00             mov eax,[eax]
004050F4 8BD8             mov ebx,eax
Project1.dpr.12: writeln(i);
004050F6 A1AC674000       mov eax,[$004067ac]
004050FB 8BD3             mov edx,ebx

No a nakonec nejhorší varianta - zapnutá kontrola řetězců a vypnuté inline optimalizace.

program Project1;

{$APPTYPE CONSOLE}
{$STRINGCHECKS ON} // ekvivalent nastavení v options
{$INLINE OFF}  // ekvivalent nastavení v options
var
  s: string;
  i: Integer;
begin
  s:= 'delphi.cz';
  i := Length(s);
  writeln(i);
end.

Výsledek obsahuje volání EnsureUnicodeString, což určitě není optimální.

Project1.dpr.11: s:= 'delphi.cz';
004050D7 B8389B4000       mov eax,$00409b38
004050DC BA34514000       mov edx,$00405134
004050E1 E83EEFFFFF       call @UStrAsg
Project1.dpr.12: i := Length(s);
004050E6 B8389B4000       mov eax,$00409b38
004050EB E8E4EEFFFF       call @EnsureUnicodeString
004050F0 E87FF0FFFF       call @UStrLen
004050F5 8BD8             mov ebx,eax
Project1.dpr.13: writeln(i);
004050F7 A1AC674000       mov eax,[$004067ac]
004050FC 8BD3             mov edx,ebx

Vypnutím kontroly formátu řetězců tedy získáte malé zvýšení rychlosti a o trochu menší výslednou binárku. Stejně ale autoři měli udělat volbu primárně vypnutou.

Tagy: ,

Optimalizace

Komentování ukončeno

Naše nabídka

MVP
Ing. Radek Červinka - Embarcadero MVP
profil na linkedin, Twitter:@delphicz

Nabízím placené poradenství a konzultace v oblasti programování a vývoje SW.
Dále nabízíme i vývoj speciálního software na zakázku.

Neváhejte nás kontaktovat (i ohledně reklamy).

love Delphi

O Delphi.cz

Delphi je moderní RAD nástroj podporující tvorbu nativních aplikací pro platformu Win32, Win64, Mac OSX, Linux a na iPhone a Android.

Delphi.cz je nezávislý portál pro uživatele Delphi. Portál není koncipován pro úplné začátečníky, i když i ti se zde nebudou nudit, ale spíše na programátory, kteří již něco znají a chtějí své znalosti dále rozvíjet a sledovat novinky.

Poslední komentáře

Comment RSS

Dle měsíců