2013-08-15 10 views
5

jestem ciekaw, co się dzieje z tego kawałka kodu w Delphi 2010:Dołączanie UnicodeString do WideString w Delphi

function foo: WideString; 
var 
    myUnicodeString: UnicodeString; 
begin 
    for i:=1 to 1000 do 
    begin 
    myUnicodeString := ... something ...; 

    result := result + myUnicodeString; // This is where I'm interested 
    end; 
end; 

ile konwersji smyczkowe są zaangażowani, a są jakieś szczególnie złe wydajność mądry?

Wiem, że funkcja powinna po prostu zwrócić wartość UnicodeString, ale widziałem ten wzorzec w kodzie strumieniowym VCL i chcę zrozumieć proces.

+0

Czy próbowałeś to sprawdzić w oknie procesora debuggera? – OnTheFly

+0

@OnTheFly: W rzeczywistości jest to część projektu C++ Builder i z jakiegoś powodu BCB2010 nie lubi ustawiania punktów przerwania w kodzie VCL ... Postaram się przejść przez kolejne. – Roddy

+0

Jeśli nie masz Delphi do badania wygenerowanego kodu dla twojego tescase, mogę wysłać demontaż, ale naprawdę nie jestem pewien jak go przedstawić w użytecznej formie ... – OnTheFly

Odpowiedz

8

Aby odpowiedzieć na pytanie o to, co kod jest rzeczywiście robi to stwierdzenie:

result := result + myUnicodeString; 

wykonuje następujące operacje:

  1. połączeń System._UStrFromWStr() przekonwertować Result do temp UnicodeString

  2. dzwoni System._UStrCat(), aby połączyć myUnicodeString na t emp

  3. dzwoni System._WStrFromUStr(), aby przekonwertować temp na WideString i przypisać go z powrotem do Result.

Jest System._WStrCat() funkcja łącząc się WideString na kolumnę WideString (i System._UStrCat() do UnicodeString). Jeśli CodeGear/Embarcadero był mądrzejszy w tym zakresie, mogły one wdrożyć przeciążenie System._WStrCat(), które pobiera UnicodeString jako dane wyjściowe i WideString jako dane wyjściowe (i odwrotnie, aby połączyć dane WideString z UnicodeString). W ten sposób nie będą już potrzebne żadne konwersje. Zarówno WideString i UnicodeString są kodowane jako UTF-16 (również w większości, ale nie będę się w to tutaj), więc łączenie ich ze sobą jest tylko kwestia pojedynczego przydziału i ruchu, podobnie jak podczas złączenie dwóch UnicodeString s lub dwóch WideString s razem.

+0

Dzięki Remy. To wyjaśnia wiele! – Roddy

+0

+1 za analizę, której nie mogłem dostarczyć –

4

Osiągi są słabe. Nie ma potrzeby kodowania konwersji, ponieważ wszystko jest zakodowane w UTF-16. Jednak WideString jest opakowaniem typu COM BSTR, który działa gorzej niż natywny UnicodeString.

Naturalnie powinieneś preferować wykonywanie całej swojej pracy z typami natywnymi, UnicodeString lub TStringBuilder, i konwersję do WideString w ostatnim możliwym momencie.

To ogólnie dobra polityka. Nie chcesz używać WideString wewnętrznie, ponieważ jest to typ czysto interopowy. Więc tylko konwertuj na (i od) WideString na granicy międzyoperacyjnej.

+0

Dzięki.Jestem szczególnie ciekawy, czy łańcuch concat (wide: = wide + uni) dzieje się w domenie Unicode lub Wide. Jeśli jest to kod Unicode, bierzesz pod uwagę dwie konwersje. (wide-> uni, concat, uni-> wide) – Roddy

+0

Nie znam tego szczegółu z mojej głowy. Ale trywialnie łatwo jest pracować z debuggerem. Coś, czego teraz nie mam. Tak czy inaczej, nie chcesz tego. Wykonaj całą swoją pracę z TStringBuilder i przekonwertuj na WideString tak późno, jak to możliwe. Wszystkie te konkatenacje byłyby złe nawet z czystymi natywnymi strunami. Ciężkie na stercie. –

+0

To w rzeczywistości nie jest mój kod. Jest w classes.pas w D2010 (CombineWideString). Miałem problem, w którym formularz z pojedynczą właściwością ciągową 4MB (tak, ale jest dobry powód!) Zajął 2,5 minuty (!), Aby załadować podczas korzystania z DFM tekstu, a pod drugą z binarnym. – Roddy