AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Sonstige Fragen zu Delphi Delphi Funktionsaufruf: Dauert immer länger. Warum?
Thema durchsuchen
Ansicht
Themen-Optionen

Funktionsaufruf: Dauert immer länger. Warum?

Ein Thema von Go2EITS · begonnen am 11. Apr 2009 · letzter Beitrag vom 12. Apr 2009
Antwort Antwort
Seite 1 von 2  1 2      
Go2EITS

Registriert seit: 25. Jun 2006
519 Beiträge
 
Delphi 7 Personal
 
#1

Funktionsaufruf: Dauert immer länger. Warum?

  Alt 11. Apr 2009, 08:05
Hallo, nachstehendes Programm bitte einmal ausprobieren.

In der vorliegenden Version wird Clearstring1 immer langsamer. Ich kann es nicht erklären.
Die drei Funktionen unterscheiden sich nur durch die Konstanten:
1. ValidChars = ['a'..'z','A'..'Z'];
2. ValidChars = ['a'..'z','A'..'Z',' '];
3. ValidChars = ['a'..'z','A'..'Z','ä','ö','ü','Ä','Ö','Ü','ß',' '];

Paradoxerweise ist die zweite Variante schneller als die erste! (Ich habe nur ein SPACE in ValidChars hinzugefügt). Probiert dies bitte aus.

Zur Funktion: Clearstring gibt einen "bereinigten" String zurück.
Welche Zeichen dann enthalten sind, wird mit z.B. ValidChars = ['a'..'z','A'..'Z']; definiert.
Delphi-Quellcode:
program ClearString;

{$APPTYPE CONSOLE}

uses
  //FastMM4,FastMove,
  SysUtils, // Für Profiler.inc notwendig
  Windows; // Für Profiler.inc notwendig
{$include Profiler.inc}
var
  xx,ii:Integer;
// Langsame Variante
function ClearStr1(const Str: string): String;
var
  i:Integer;
const
ValidChars = ['a'..'z','A'..'Z'];
  begin
  if Str = 'then Exit;
  for i:=1 to Length(Str) do if str[i] in ValidChars then result:=result+Str[i];
end;

// Diese ist schneller...
function ClearStr2(const Str: string): String;
var
  i:Integer;
const
ValidChars = ['a'..'z','A'..'Z',' ']; // Schnelle Variante
  begin
  if Str = 'then Exit;
  for i:=1 to Length(Str) do if str[i] in ValidChars then result:=result+Str[i];
end;

function ClearStr3(const Str: string): String;
var
  i:Integer;
const
ValidChars = ['a'..'z','A'..'Z','ä','ö','ü','Ä','Ö','Ü','ß',' '];
  begin
  if Str = 'then Exit;
  for i:=1 to Length(Str) do if str[i] in ValidChars then result:=result+Str[i];
end;


begin
Writeln('Teste... ClearStr1');
for xx:=1 to 10 do
   begin
   Start;
   for ii:=1 to 10000 do ClearStr1('>a-uf d?er Ma!uer<');
   Stopp;
   end;
Writeln('Ergebnis muss - aufderMauer - sein:');
Writeln(ClearStr1('>a-uf d?er Ma!uer<'));Writeln;


Writeln('Teste... ClearStr2');
for xx:=1 to 10 do
    begin
    Start;
    for ii:=1 to 10000 do ClearStr2('>a-uf d?er Ma!uer<');
    Stopp;
    end;
Writeln('Ergebnis muss - auf der Mauer - sein:');
Writeln(ClearStr2('>a-uf d?er Ma!uer<'));Writeln;

Writeln('Teste... ClearStr3');
for xx:=1 to 10 do
    begin
    Start;
    for ii:=1 to 10000 do ClearStr3('>a-uf d?er Ma!uer<');
    Stopp;
    end;
Writeln('Ergebnis muss - auf der Mauer - sein:');
Writeln(ClearStr3('>a-uf d?er Ma!uer<'));Writeln;

Writeln('- ProgrammEnde mit [ENTER] -');Readln;

end.
Die Include:
Delphi-Quellcode:
// Date: 08.04.2009
// File: Profiler.inc

//Timer Variablen
 var Profiler_StartWert, Profiler_StopWert, Profiler_Freq: int64;

/// Profiler Routinen Start...
procedure Start;
begin
QueryPerformanceFrequency(Profiler_Freq);
QueryPerformanceCounter(Profiler_StartWert);
end;

procedure Stopp;
begin
QueryPerformanceCounter(Profiler_StopWert);
Writeln('Profiler: '+floattostr(((Profiler_StopWert-Profiler_StartWert)/Profiler_Freq)*1000)+' ms');
end;
/// ...Profiler Routinen Ende
Ich habe, eigentlich nur aus "Spaß", die FastMM4 mit eingebunden, da funktioniert es plötzlich.
Ist es ein BUG in Delphi 7? Und wenn ja, kann ich diesen ohne FastMM4 umgehen?
[Edit: Titel geändert]
  Mit Zitat antworten Zitat
Hawkeye219

Registriert seit: 18. Feb 2006
Ort: Stolberg
2.227 Beiträge
 
Delphi 2010 Professional
 
#2

Re: Clearstring:Aufruf dauert immer länger.

  Alt 11. Apr 2009, 09:07
Hallo,

du solltest den Rückgabewert deiner Funktionen initialisieren, sonst wird der String immer länger: klick

Gruß Hawkeye
  Mit Zitat antworten Zitat
Go2EITS

Registriert seit: 25. Jun 2006
519 Beiträge
 
Delphi 7 Personal
 
#3

Re: Clearstring:Aufruf dauert immer länger.

  Alt 11. Apr 2009, 09:15
@Hawkeye219:
Opps, so einfach. Es funktioniert. Allein wäre ich nie darauf gekommen. Danke!
Wenn man FastMM4 und FastNove einbindet, wird die Funktion noch schneller.
  Mit Zitat antworten Zitat
11. Apr 2009, 09:20
Dieses Thema wurde von "mkinzler" von "Programmieren allgemein" nach "Sonstige Fragen zu Delphi" verschoben.
Ist eine Delphi-Frage
jbg

Registriert seit: 12. Jun 2002
3.481 Beiträge
 
Delphi 10.1 Berlin Professional
 
#5

Re: Clearstring:Aufruf dauert immer länger.

  Alt 11. Apr 2009, 09:55
Und wenn man statt "result:=result+Str[i]" einmalig die Worstcase-Länge bestimmt und am Ende dann die echte Länge setzt, wird das ganze noch schneller.
  Mit Zitat antworten Zitat
Go2EITS

Registriert seit: 25. Jun 2006
519 Beiträge
 
Delphi 7 Personal
 
#6

Re: Funktionsaufruf: Dauert immer länger. Warum?

  Alt 11. Apr 2009, 11:51
@Jbg: Wie soll das gehen?
Wenn ich einmal den Übergabestring durchlaufe und gleichzeitig den neuen String bilde mit "result:=result+Str[i]" habe ich wohl die schnellste Version.
Ein
Delphi-Quellcode:
for i:=1 to Length(Str) do if str[i] in ValidChars then s:=s+str[i];
result:=s;
bringt keinen Geschwindigkeitsvorteil.
Ich gehe mal davon aus, dass "str[i] in ValidChars " abbricht, wenn es einen gültigen Char gefunden hat und nicht immer bis zum Ende durchläuft. Sonst dürfte eine Tabelle schneller sein.
  Mit Zitat antworten Zitat
Go2EITS

Registriert seit: 25. Jun 2006
519 Beiträge
 
Delphi 7 Personal
 
#7

Re: Funktionsaufruf: Dauert immer länger. Warum?

  Alt 11. Apr 2009, 13:41
Ich habe mal beide Versionen nachstehend eingefügt.
a) Version mit der Mengenabfrage und b) Abfrage mit einer Tabelle.
Delphi-Quellcode:
program ClearString1;

{$APPTYPE CONSOLE}

uses
  FastMM4, FastMove,
  SysUtils, // Für Profiler.inc notwendig
  Windows; // Für Profiler.inc notwendig
{$include Profiler.inc}
var
  xx,ii:Integer;
var
  ValidChars1: array[1..53] of Char = ('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',' ','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z');

// Alte Version:
function ClearStrAlt(const Str: string): String;
var
  i:Integer;
const
ValidChars = ['a'..'z','A'..'Z','ä','ö','ü','Ä','Ö','Ü','ß',' '];
  begin
  if Str = 'then Exit;
  result:='';
  for i:=1 to Length(Str) do if str[i] in ValidChars then result:=result+Str[i];
end;

//Neue Version:
function ClearStr(const Str: string): String;
var
  i,x:Integer;
  begin
  if Str = 'then Exit;
  result:='';
  for i:=1 to Length(Str) do
      begin
      for x:=1 to 53 do
      if (str[i] = ValidChars1[x]) then //Hier durchlaufen wir die Tabelle
         begin
         result:=result+Str[i];
         Break; //... und for-Schleife verlassen.
         end;
  end;
end;

begin

Writeln('Teste... ClearStr - Alte Version:');
for xx:=1 to 10 do
   begin
   Start;
   for ii:=1 to 100000 do ClearStrAlt('>a-uf d?er Ma!uer<');
   Stopp;
   end;
Writeln('Ergebnis muss - auf der Mauer - sein:');
Writeln(ClearStrAlt('>a-uf d?er Ma!uer<'));Writeln;

Writeln('Teste... ClearStr - Neue Version:');
for xx:=1 to 10 do
   begin
   Start;
   for ii:=1 to 100000 do ClearStr('>a-uf d?er Ma!uer<');
   Stopp;
   end;
Writeln('Ergebnis muss - auf der Mauer - sein:');
Writeln(ClearStr('>a-uf d?er Ma!uer<'));Writeln;
Writeln('- ProgrammEnde mit [ENTER] -');Readln;
end.
Fazit: Die Version mit der Menge ist deutlich schneller, als die mit der Tabelle.
Das Einbinden von FastMM4 und Move bringt nochmals einen deutlichen Gewindigkeitsschub.
  Mit Zitat antworten Zitat
Cyf

Registriert seit: 30. Mai 2008
407 Beiträge
 
Lazarus
 
#8

Re: Funktionsaufruf: Dauert immer länger. Warum?

  Alt 11. Apr 2009, 14:47
Delphi-Quellcode:
SetLength(Result, Length(Str));
for ...
begin
  Result[i]:= Str[i]; //falsch, siehe nächster Post
  Inc(Count);
end;
SetLength(Result, Length(Count));
[Edit] http://www.delphi-treff.de/delphi-st...e/anweisungen/

[Edit2]Ja, natürlich.
Man kann einen Barbier definieren als einen, der alle diejenigen rasiert, und nur diejenigen, die sich nicht selbst rasieren.
Rasiert sich der Barbier?
  Mit Zitat antworten Zitat
Christian Seehase
(Co-Admin)

Registriert seit: 29. Mai 2002
Ort: Hamburg
11.105 Beiträge
 
Delphi 11 Alexandria
 
#9

Re: Funktionsaufruf: Dauert immer länger. Warum?

  Alt 11. Apr 2009, 16:09
Moin Cyf,

vielleicht besser so

Zitat von Cyf:
Code:
SetLength(Result, Length(Str));
for ...
begin
  Result[[color=red]Count[/color]]:= Str[i];
  Inc(Count);
end;
SetLength(Result, Length(Count));
[EDIT]
@Go2EITS:
Ein String ist eigentlich ein dynamisches Array.
Wenn Du dieses verlängerst, muss, normaler Weise, jedesmal der Speicher neu angefordert, und der bisherige Inhalt dort hineinkopiert werden. Deswegen sollte man, nach Möglichkeit, ein dynamisches Array von Anfang an so gross machen, wie erforderlich, und erst zum Schluss die Länge setzen.
(Wenn man die Länge nicht vorab genau kennt, empfiehlt es sich, die Länge vorab so gut wie möglich abzuschätzen, und dann, ggf. um mehere Elemente vergrössern, z.B. um 10% des ursprünglichen Schätzwertes. Um welchen Wert man vergrössert sollte davon abhängen, wie gut man den Initialwert abschätzen kann.)
[/EDIT]
Tschüss Chris
Die drei Feinde des Programmierers: Sonne, Frischluft und dieses unerträgliche Gebrüll der Vögel.
Der Klügere gibt solange nach bis er der Dumme ist
  Mit Zitat antworten Zitat
Go2EITS

Registriert seit: 25. Jun 2006
519 Beiträge
 
Delphi 7 Personal
 
#10

Re: Funktionsaufruf: Dauert immer länger. Warum?

  Alt 11. Apr 2009, 16:55
Danke Christian und Cyf, nochmals 50% rausgeholt.
Kleine Änderungen am Vorschlag vorgenommen, damit der Text auch angezeigt wird:

Delphi-Quellcode:
// Zur Erinnerung:
// var
// ValidChars1: array[1..53] of Char = //('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',' //','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z');


//Neue Version mit Vorschlag von Cyf:
function ClearStrTest(const Str: string): String;
var
  i,x,count:Integer;
begin
  if Str = 'then Exit;
  result:='';
  count:=1; // Start bei 1..
  SetLength(Result, Length(Str));
  for i:=1 to Length(Str) do
      begin
      for x:=1 to 53 do
      if (str[i] = ValidChars1[x]) then //Hier durchlaufen wir die Tabelle
         begin
         Result[Count]:= Str[i];
         Inc(Count);
         Break; //... und for-Schleife verlassen.
         end;
      end;
  SetLength(result, Count-1); //... und hier 1 wieder abgezogen
end;
Möglicherweise geht es mit Pointern noch schneller?
[Edit] Damit "schlägt Tabelle die Menge", vorausgesetzt die Tabelle ist so groß wie oben.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:46 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz