Erster!!!!

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Christian
Lazarusforum e. V.
Beiträge: 6092
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Beitrag von Christian »

Denkfehler dachte der optimizer müsste das erkennen aber kann er ja nicht kann ja durchaus sinn machen
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

Bora4d
Beiträge: 290
Registriert: Mo 24. Dez 2007, 13:14
OS, Lazarus, FPC: WinXP-Pro-Sp3, Xubuntu 12.04, (Laz 1.1-SVN Mai2012, FPC 2.6.1 / 2.6.0-Linux)
CPU-Target: AMD64X2

Beitrag von Bora4d »

Ich habe mal nachgetestet:

Code: Alles auswählen

for i:=0 to 10000000 do begin
  try
   inc(x);
  except
  end;
end;


ist ca 15ms schneller als

Code: Alles auswählen

for i:=0 to 10000000 do begin
   inc(x);
   if x=-1 then beep;  //nur dummy kontrolle, man will ja prüfen ob fehler ist
end;


Aber jetzt kommst, sobald man mehr als eine Variable kontrolliert, dann dauern die if-Abfragen länger, und zwar bei jede zusätzlichen Integer-Abfrage ca. 10-20 ms.
Bei string abfragen ist Exceptions schon bei der ersten string-Kontrolle schneller.

Benutzeravatar
theo
Beiträge: 8454
Registriert: Mo 11. Sep 2006, 19:01

Beitrag von theo »

Kann ich nicht bestätigen. (Linux, OpenSuse 10.2,
Free Pascal Compiler version 2.2.0 [2007/08/31] for i386)
Dieser Code:

Code: Alles auswählen

procedure TForm1.Button1Click(Sender: TObject);
var i,x:integer;
tick:Cardinal;
begin
 tick:=GetTickCount;
 for i:=0 to 10000000 do begin
  try
   inc(x);
  except
    beep;
  end;
 end;
 writeln('a: ',GetTickCount-tick);
 
 tick:=GetTickCount;
 for i:=0 to 10000000 do begin
   inc(x);
   if x=-1 then beep; 
   if x=-2 then beep;
   if x=-3 then beep;
   if x=-4 then beep;
 end;
 writeln('b: ',GetTickCount-tick);
end;


ergibt bei mir diese Messreihe:

a: 192
b: 63
a: 192
b: 62
a: 194
b: 62
a: 192
b: 60
a: 192
b: 61
a: 192
b: 62
a: 192
b: 62

Ausserdem hinkt dein Vergleich. Deine try..except Variante tut ja nix d.h. die Exception wird niemals ausgelöst.
Die if Variante hingegen vergleicht zwei Werte. Genauso mit Strings. Wie willst du mit try.. except Strings vergleichen?

_Bernd
Beiträge: 142
Registriert: Di 13. Feb 2007, 11:16

Beitrag von _Bernd »

Ich setze try.. except ebenfalls sehr selten ein. Folgender Link könnte interessant sein.

http://www.delphi-treff.de/backstage/in ... n-bloecke/

Das trifft wahrscheinlich auch auf FPC/Lazarus zu.

Gruß, Bernd.

Bora4d
Beiträge: 290
Registriert: Mo 24. Dez 2007, 13:14
OS, Lazarus, FPC: WinXP-Pro-Sp3, Xubuntu 12.04, (Laz 1.1-SVN Mai2012, FPC 2.6.1 / 2.6.0-Linux)
CPU-Target: AMD64X2

Beitrag von Bora4d »

Sorry, ich habe winxp, delphi 4 prof. verwendet. Da stimmen meine Aussagen. Als ich deine Ergebnisse mit Lazarus (heute runtergeladen) überprüft habe triftt deine Aussage für Zahlenvergleiche zu. Für string-Vergleiche ab der 2. String ist auch für Lazarus try-except besser.

"Ausserdem hinkt dein Vergleich. Deine try..except Variante tut ja nix d.h. die Exception wird niemals ausgelöst.
Die if Variante hingegen vergleicht zwei Werte. Genauso mit Strings. Wie willst du mit try.. except Strings vergleichen?"

Der Vergleich ist ja nur für Fehlerüberprüng. Die Frage war "Soll man für Fehlerüberprüfung try..except oder "if fehler ..."benutzen ?"
Nehmen wir an du hast in einer Schleife eine String-Variable die darf nie "bier" lauten ansonsten stürzt das Programm ab. Die Wahrscheinlichkeit, dass die String-Variable den Wert "bier" bekommt ist sehr gering. Du möchstest aber dein Programm sicher machen. Was würdest du benutzten try..except oder if..then? Darum ging es.


Das habe ich benutzt. Um Anzahl der if fragen oder Stringvergleiche zu kontrollieren habe ich einige if's aktviert bzw. deaktiviert.

Code: Alles auswählen

astr:='dummstring';
  x:=0;
  Tick:=GetTickCount;
  for i:=0 to 10000000 do begin
   try
    inc(x);
   except
   end;
  end;
   Label1.Caption:='Try-Except in ms:'+ Inttostr(GetTickCount-Tick);
 
  x:=0;
  Tick:=GetTickCount;
  for i:=0 to 10000000 do begin
    if x=-1 then beep;
    if i=-1 then beep;
    if a=-1 then beep;     if b=-1 then beep;     if c=-1 then beep;     if d=-1 then beep;
   // if astr='fehler' then beep;
    inc(x);
  end;
   Label2.Caption:='if-then in ms:'+ Inttostr(GetTickCount-Tick);



Leider muß ich Lazarus und Freepascal wieder deinstallieren. Ich wollte so gern umsteigen aber Freepascal ist zu langsam und immer noch nicht ausgereift. Try..except block dauert bei mir mit delphi-4-prof 74ms und mit Lazarus 343ms. Das ist fast Schneckentempo.

Edit:
Try..except außerhalb der Schleife gehört ist auch schon klar, es ging nur um Performancetest.

Benutzeravatar
theo
Beiträge: 8454
Registriert: Mo 11. Sep 2006, 19:01

Beitrag von theo »

Bora4d hat geschrieben:Der Vergleich ist ja nur für Fehlerüberprüng. Die Frage war "Soll man für Fehlerüberprüfung try..except oder "if fehler ..."benutzen ?"
Nehmen wir an du hast in einer Schleife eine String-Variable die darf nie "bier" lauten ansonsten stürzt das Programm ab.


Aber wie vergleichst du das denn? Ein try except allein macht diesen Stringvergleich doch nicht!
In deinem try..except Block überprüfst du ja nix.
Es ist schon klar, dass ein Stringvergleich dauert, aber den musst du ja im try..except auch machen um die gleiche Funktionalität zu erhalten.

Bora4d hat geschrieben:Leider muß ich Lazarus und Freepascal wieder deinstallieren. Ich wollte so gern umsteigen aber Freepascal ist zu langsam und immer noch nicht ausgereift. Try..except block dauert bei mir mit delphi-4-prof 74ms und mit Lazarus 343ms. Das ist fast Schneckentempo.

Aufpassen mit solchen Messungen! Ich weiss es nicht, aber es ist gut möglich, dass Delphi einen leeren try..except block wegoptimiert und FPC nicht.
In realen Situationen kann es anders aussehen.
Ausserdem finde ich so eine Einzelmessung keinen Grund, auf Freepascal zu verzichten.

Bora4d
Beiträge: 290
Registriert: Mo 24. Dez 2007, 13:14
OS, Lazarus, FPC: WinXP-Pro-Sp3, Xubuntu 12.04, (Laz 1.1-SVN Mai2012, FPC 2.6.1 / 2.6.0-Linux)
CPU-Target: AMD64X2

Beitrag von Bora4d »

Theo ich mache für dich konktreten Beispiel:

Code: Alles auswählen

for i:=0 to 10000000 do begin
    einstring:=einstringarray[i];    //einstringarray[i] hat vielleicht irgendwo den Wert "bier"
    .....
     in diesen Zeilen wird einstring bearbeitet
     wenn jetzt hier der einstring den Wert "bier" hat stürzt das programm ab.
    .... 
  end;

Die Frage ist jetzt wie willst du jetzt das Programm sicher machen und was wird schneller bearbeitet?
try..except

Code: Alles auswählen

for i:=0 to 10000000 do begin
    einstring:=einstringarray[i];    //einstringarray[i] hat vielleicht irgendwo den Wert "bier"
    try
    .....
     in diesen Zeilen wird einstring bearbeitet
     wenn jetzt hier der einstring den Wert "bier" hat stürzt das programm ab.
    .... 
 
    except
      einstring:='standard';       
    end;
  end;


oder if-abfrage:
try..except

Code: Alles auswählen

for i:=0 to 10000000 do begin
    einstring:=einstringarray[i];    //einstringarray[i] hat vielleicht irgendwo den Wert "bier"
    if einstring='bier' then einstring:='standard';       
    .....
     in diesen Zeilen wird einstring bearbeitet
     wenn jetzt hier der einstring den Wert "bier" hat stürzt das programm ab.
    .... 
  end;

Das war der Vergleich, ich hoffe jetzt hast du es.


Ich habe mal den Code modifiziert damit es nicht optimiert wird und da die sind fast gleich. Und bei mehreren variablen-Checks scheint try-except bessere Lösung zu sein.

Code: Alles auswählen

x:=0;
  Tick:=GetTickCount;
  for i:=0 to 1000 do begin
   try
    inc(x);
    caption:=IntToStr(x);
   except
    x:=0;
   end;
  end;
   Label1.Caption:='Try-Except in ms:'+ Inttostr(GetTickCount-Tick);
 
  x:=0;
  Tick:=GetTickCount;
  for i:=0 to 1000 do begin
    if x=-1 then beep;
    inc(x);
    caption:=IntToStr(x);
  end;
   Label2.Caption:='if-then in ms:'+ Inttostr(GetTickCount-Tick);


Ich habe jetzt im Netz gelesen, dass Free Pascal doch nicht so schlect sein soll. Ich probiers mal richtig aus.

Christian
Lazarusforum e. V.
Beiträge: 6092
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Beitrag von Christian »

Freepascal schneidet in "richtigen" Benchmarks wesentlich besser ab als Delphi. Und schon gar als Delphi 4. Da kommt er sogar gut an den gcc ran. Und davon ist Delphi Meilenweit entfernt.
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

Benutzeravatar
theo
Beiträge: 8454
Registriert: Mo 11. Sep 2006, 19:01

Beitrag von theo »

@Bora4d: Schon klar. Aber daraus würde ich auch noch keine allgemeinen Schlüsse ziehen.
Es kommt nämlich auch drauf an, wie oft "bier" vorkommt. Wenn die Exception nämlich erst mal ausgelöst wird, dauert's erst richtig lange, während die Stringvergleich Variante immer gleich ist.
Ausserdem schreibts du ja nicht, was in der "Blackbox" beim try..except alles passiert um die Exception auszulösen, während du im anderen Fall den Vergleich im Code hast.
--
mit caption:=IntToStr(x);
wäre ich Vorsichtig. Caption setzen, beepen etc. kann lange dauern, sodass es die eigentliche Messung verdeckt.

Antworten