Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Schnelles "Addieren" von Strings


WeBsPaCe - Mo 28.04.08 12:47
Titel: Schnelles "Addieren" von Strings
Tach, ;-)

Beispiel:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils;

var
  ig: Integer;
  ws: WideString;
  dt: TDateTime;

begin
  ws := '';
  while True do
    begin
      dt := NOW;
      for ig := 0 to 500 do
        ws := ws + 'foo';
      WriteLn(FormatDateTime('SS.ZZZ', NOW - dt));
    end;
end.


Ich bekomm mit der Zeit immer größere Differenzen. Vermutung: da ws immer größer wird, dauert die Addition ws + 'foo' immer länger.

Was also tun? Denn prinzipiell stell ich mir das doch nicht falsch vor, dass die Operation immer dieselbe ist, also nicht länger dauern sollte/dürfte.

Danke schonmal, bis dann,
WeBBy


Tilo - Mo 28.04.08 13:10

Ich denke das liegt am Typ Widestring. Dieser kann bis zu 2GB(Rad Studio 2007) groß werden. Wenn Du nun den String erweiterst und er nicht mehr an die Speicherstelle passt wo er im Moment steht so muss er an eine andere Stelle kopiert werden was Zeit benötigt. Und je länger der String ist desto mehr muss kopiert werden.
Und ich schätze es kommt noch etwas anderees hinzu: Du fügst nicht einfach nur an, sondern Du weist der StringVariable immer einen neuen Wert zu. Es wird der alte Wert eingelesen, der neue Teilstring addiert und dann das Ergebniss der Variablen zugewiesen.

Wenn es nicht so ist bitte ich um Korrektur.


WeBsPaCe - Mo 28.04.08 13:17

Tach! :-)

user profile iconTilo hat folgendes geschrieben:
Ich denke das liegt am Typ Widestring. Dieser kann bis zu 2GB(Rad Studio 2007) groß werden. Wenn Du nun den String erweiterst und er nicht mehr an die Speicherstelle passt wo er im Moment steht so muss er an eine andere Stelle kopiert werden was Zeit benötigt. Und je länger der String ist desto mehr muss kopiert werden.

Okay, aber das Problem hab ich doch in jedem Fall, oder? Auch bei einem String, wird der ab einer gewissen Größe nicht mehr da hinpassen, wo er war. Oder nicht?

user profile iconTilo hat folgendes geschrieben:
Und ich schätze es kommt noch etwas anderees hinzu: Du fügst nicht einfach nur an, sondern Du weist der StringVariable immer einen neuen Wert zu. Es wird der alte Wert eingelesen, der neue Teilstring addiert und dann das Ergebniss der Variablen zugewiesen.

Genau, das mein ich auch. Eine Idee, wie ich das anders realisieren kann?

MfG,
WeBBy


alzaimar - Mo 28.04.08 13:30
Titel: Re: Schnelles "Addieren" von Strings
user profile iconWeBsPaCe hat folgendes geschrieben:
... dass die Operation immer dieselbe ist, also nicht länger dauern sollte/dürfte.

Nein! Wie schon erwähnt, wird der String immer länger. Leere den String also vor der For-Schleife und dann sollte das zu anderen Ergebnissen führen.


Tilo - Mo 28.04.08 13:42

Vielleicht hilft die Funktion appendstr()?


alzaimar - Mo 28.04.08 13:45

Nee, nee. Es ging ihm um das scheinbare Paradoxon, das ein und die selbe Funktion immer länger braucht. Aber das hat sich jetzt wohl geklärt, denn es ist gar nicht ein und die selbe Funktion ;-)


WeBsPaCe - Mo 28.04.08 14:57

Tach. :-)

user profile iconalzaimar hat folgendes geschrieben:
Nee, nee. Es ging ihm um das scheinbare Paradoxon, das ein und die selbe Funktion immer länger braucht. Aber das hat sich jetzt wohl geklärt, denn es ist gar nicht ein und die selbe Funktion ;-)

Nicht so ganz: ich würde mal folgende Unterscheidung machen:
Weg 1: Ich habe einen Korb mit Äpfeln, nehme die Äpfel heraus, lege einen mehr dazu und werf wieder alles in den Korb rein
Weg 2: Ich habe einen Korb mit Äpfeln und werfe den zusätzlichen Apfel einfach gleich dazu

Das Ergebnis ist dasselbe, bloß dauert Weg 1 deutlich länger als Weg 2. Delphi nimmt anscheinend Weg 1, wenn ich ws := ws + 'foo'; schreibe. Sinnvoller, da zeitsparender, ist allerdings Weg 2, also: wie setze ich Weg 2 in Delphi um?

user profile iconTilo hat folgendes geschrieben:
Vielleicht hilft die Funktion appendstr()?

Funktioniert bei mir mit WideStrings nicht. Mach ich was falsch?

MfG,
WeBBy


Delete - Mo 28.04.08 15:19

Definiere eine Zielvariable und lege deren Größe mit SetLength auf die Größe des resultierenden Strings fest.


WeBsPaCe - Mo 28.04.08 15:24

Tach.

user profile iconLuckie hat folgendes geschrieben:
Definiere eine Zielvariable und lege deren Größe mit SetLength auf die Größe des resultierenden Strings fest.

Du meinst von vorneherein, oder? Also bevor überhaupt irgendwas gespeichert wurde? Problem: Da weiß ich leider noch nicht, wie groß das Teil am Ende wird.

Ansonsten versteh ich nicht, was du meinst. ;)

MfG,
WeBBy


Lannes - Mo 28.04.08 15:48

Hallo,

Du weist aber zwischendurch wie groß es wird.
Um bei Deinem Beispiel zu bleiben, vergößer den Korb so, das der Apfel reinpasst.
Denke user profile iconLuckie meint es in etwa so:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
var wsErg, ws   : WideString;
    x, z, zz, i : Integer;
    dt          : TDateTime;
begin
  wsErg := '';
  ws := 'foo';
  x := 500;
  i := 1;
  while True do
    begin
    dt := NOW;
    Setlength(wsErg,(x * Length(ws)) + Length(wsErg));
    for z := 1 to x do
      for zz := 1 to Length(ws) do
        begin
        wsErg[i] := ws[zz];
        inc(i);
        end;
    WriteLn(FormatDateTime('SS.ZZZ', NOW - dt)); 
    end;
end.


hazard999 - Mo 28.04.08 16:34

TStringList nehmen.

verwendet andere Speicherverwaltung als die Compiler-Magic von string-concat.

Habe das selbe Problem auch schon gehabt. Verursacht zusätzlich eine fürchterliche Speicherfragmentierung.

r u

René


WeBsPaCe - Mo 28.04.08 21:09

Okay, vielen Dank für die Antworten. ;-)

MfG,
WeBBy