Erster!!!!

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Benutzeravatar
theo
Beiträge: 10497
Registriert: Mo 11. Sep 2006, 19:01

Erster!!!!

Beitrag von theo »

Zunachst will ich mal der Erste sein in 2008!!!! geschafft!! :wink:
Habe grippalen Infekt und kann deshalb nicht so richtig ausgehen zum feiern.

Super Feuerwerk auf dem Portal Monta! "ein erfolgreiches Jahr 2008" wäre mir allerdings lieber als ein ebensolches 2007. :lol:

Aber natürlich auch von mir: Viel Spass im neuen Jahr!

Und dann noch eine Frage an alle zum neuen Jahr:

Wie haltet ihr es eigentlich mit den Exceptions?
Bin gestern aufgrund dieses Postings drauf gekommen:
viewtopic.php?t=1295

Mir ist dabei aufgefallen, dass ich sowas nie in try .. finally setzen würde.
Ich stand allerdings schon immer etwas auf Kriegsfuss mit den Exceptions.
Ich finde das eine gute Sache, wenn man z.B. Dateizugriffe machen will, oder als High Level Wrapper für Plugin Architekturen etc. Aber sonst frag ich mich immer wozu das gut sein soll.

Wenn ich Code schreibe z.B. in Komponenten, muss ich doch wissen was geschehen kann und muss das sinngemäss bearbeiten. Ein try... except um einen nicht verstandenen Code nützt doch eigentlich auch nicht viel.
Wenn ich nicht verstehe was passieren kann, kann ich doch auch keine sinnvolle Ausnahmebehandlung machen - wenn ich es verstehe kann ich es verhindern.
Es kann zwar ein "lazy way" sein, dabei muss man aber wissen, dass Exceptions einen Rattenschwanz von Code aufrufen, was Performance-mässig nicht optimal ist.
In meinen Komponenten "raise" ich höchstens mal eine, wenn eine Voraussetzung nicht erfüllt ist

Wie denkt ihr darüber?

monta
Lazarusforum e. V.
Beiträge: 2809
Registriert: Sa 9. Sep 2006, 18:05
OS, Lazarus, FPC: Linux (L trunk FPC trunk)
CPU-Target: 64Bit
Wohnort: Dresden
Kontaktdaten:

Beitrag von monta »

Super Feuerwerk auf dem Portal Monta! "ein erfolgreiches Jahr 2008" wäre mir allerdings lieber als ein ebensolches 2007. Laughing


:oops: da hast du mich erwischt...ist aber schon korrigiert ;)

Man müsste bei der Frage wohl gezielter nach Ressourcenschutzblock und Exceptionbehandlung unterscheiden, auch wenn es sich indirekt bedingt.

Also Ressourcenschutzblöcke setz ich eigentlich immer, aber mehr aus dem Grund, weils in den Tutorials so stand und ich von anfang an es so gemacht hab. Bisher hatte ich auch keinen Grund daran zu zweifel und werds weiterhin machen, auch wenn bei ner Stringliste beispielsweise wirklich nicht viel schief gehen kann, aber es kommt trotzdem aus prinziep nen Ressourcenschutzblock drum. Für meinen Geschmack muss aber, bezogen auf dein Beispiel das Create auf jeden Fall vor das finall, was will man den Freigeben, wenns beim create nen fehler gibt, gibts bei der Freigabe auch nen Fehler, der dann nicht abgefangen ist.


Mit try except arbeite ich auch sehr wenig. Ich hab das vertrauen in meinen Code, das er ohne auskommt. In Functionen bspw mit Netzwerk/Dateizugriff nutz ich es, wie du auch schon geschrieben hast, um ein eventuelles false zurückzugeben bzw. Fehlermeldung usw. Da ist try except halt einfach teilweise die einfachste Methode. Aber eine gezielte Exceptionabfrage füür ich wenn nur sehr selten aus.
Johannes

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

Beitrag von theo »

Hast ja recht, ich will das auch keinem ausreden.
Aber ich frage mich halt schon, was z.B. mit der Stringlist schiefgehen soll.
Höchstens wenn du keinen (Auslagerungs-) Speicher mehr frei hast, aber das ist sowieso der GAU, was soll man da noch handeln?
Für mich wiegt das die Komplizierung/Unleserlichkeit des Codes einfach nicht auf.

Generell stellt sich für mich immer wieder die Frage: Exceptions raisen OK, Exceptions abfangen OK, aber was tun?

Oder in diesem Falle: Wenn kein Arbeitsspeicher mehr frei ist, was hilft mir dann das finally ..free ? Wie soll mein Programm weiterfahren?

Mir ist das noch nie untergekommen, und falls doch, wäre es dann nicht die Aufgabe des Betriebssystems zu melden, dass mein Programm Speicher verlangt den es nicht bekommen kann?

Ich stelle jetzt mal ein freche These auf:
Exception-handling hat in Komponenten und Worker-Units/Prozeduren nichts verloren.
Diese sollen höchstens Exceptions raisen.
Exception Handling ist nur was für das Anwendungs-Level.
im Sinne:

try
MyComponent.LoadFromFile
except
Sag dem User, dass das nicht geht.
end;

Und ich lasse mich gerne von einer guten Erklärung überzeugen. Ich programmiere allerdings seit rund 10 Jahren mit Delphi/Lazarus und mir war dieser Exceptionismus noch nie ganz klar.

Euklid
Lazarusforum e. V.
Beiträge: 2808
Registriert: Fr 22. Sep 2006, 10:38
OS, Lazarus, FPC: Lazarus v2.0.10, FPC 3.2.0
Wohnort: Hessen
Kontaktdaten:

Beitrag von Euklid »

Schöne Animation, monta.

theo hat geschrieben:Ich stelle jetzt mal ein freche These auf:
Exception-handling hat in Komponenten und Worker-Units/Prozeduren nichts verloren.


Wir programmieren in Promathika zur Zeit an extrem zeitkritischen Funktionen. Hier treten nur in ganz bedingten Ausnahmefällen Error auf. Diese Ausnahmefälle sind bekannt und könnten durch if-Verzweigungen abgefangen werden. Jedoch müssten diese if-Verzweigungen auch für den Fall durchlaufen werden, in dem der Error nicht auftreten würde - was allermeistens der Fall wäre. Folge: Die If-Abzweigungen würden die zeitkritischen Routinen ziemlich bremsen, obwohl der Error ziemlich selten (fast nie) auftritt.
Zur Zeit überlegen wir uns, ob es nicht sinnvoller ist, auf die If-Verzweigungen zu verzichten und einfach ein try except zu setzen.
Was hältst du/haltet ihr davon?

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

Beitrag von theo »

Das ist kein Meinungsfrage, das kannst du leicht testen.
Das Resultat enstpricht meiner These:

Silvester besoffen hingehackter Code

Code: Alles auswählen

procedure TForm1.Button1Click(Sender: TObject);
var x,i:integer;
Tick:Cardinal;
begin
  x:=0;
  Tick:=GetTickCount;
  for i:=0 to 10000000 do
  try
   inc(x);
   except
   end;
   Caption:=Inttostr(GetTickCount-Tick);
end;


Code: Alles auswählen

procedure TForm1.Button2Click(Sender: TObject);
var x,i:integer;
Tick:Cardinal;
begin
  x:=0;
  Tick:=GetTickCount;
  for i:=0 to 10000000 do inc(x);
  Caption:=Inttostr(GetTickCount-Tick);
end;


Der Code ohne try..except läuft bei mir 5x schneller.

Try..except hat an sich einen performance penalty auch wenn keine Exception auftritt.


P.S auch diese Variante noch testen, das dauert ewig:

Code: Alles auswählen

procedure TForm1.Button1Click(Sender: TObject);
var x,i:integer;
Tick:Cardinal;
begin
  x:=0;
  Tick:=GetTickCount;
  for i:=0 to 10000000 do
  try
   inc(x);
   raise Exception.create('test');
   except
   end;
   Caption:=Inttostr(GetTickCount-Tick);
end;

pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Beitrag von pluto »

Es ist aber sichere try except z.b. werden so Dateihandle wirklich geschlossen. Gut ist es immer besser alle Fehler abzufangen mit if Anweisungen und nicht mit einer try except .

Aber so bist du auf der sicheren seite und kannst davon ausgehen das deine Objekte/Klassen auch wirklich frei geben werden. oder das dein Programm beendet wird. oder so...
MFG
Michael Springwald

monta
Lazarusforum e. V.
Beiträge: 2809
Registriert: Sa 9. Sep 2006, 18:05
OS, Lazarus, FPC: Linux (L trunk FPC trunk)
CPU-Target: 64Bit
Wohnort: Dresden
Kontaktdaten:

Beitrag von monta »

Um nochmal die Performance aufzugreifen, hat dein obiges Beispiel vielleicht noch Kapazitäten, ich würde mal schlussfolgen, das ein try...except...außerhalb der for-Schleife oftmals die selbe Funktion erfüllen kann und es wohl wesentlich performanter sein dürfte.

Also :

Code: Alles auswählen

procedure TForm1.Button1Click(Sender: TObject);
var x,i:integer;
Tick:Cardinal;
begin
  x:=0;
  Tick:=GetTickCount;
  try
   for i:=0 to 10000000 do
     inc(x);
  except
  end;
   Caption:=Inttostr(GetTickCount-Tick);
end;
Johannes

Christian
Beiträge: 6079
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 »

Ich halte von Excepions das selbe wie von Wachdogs in Microcontrollern bzw sehe sie genauso. Fehlerfreie Programme sind nunmal nicht möglich. Wärend der Enwicklung lass ich eigentlich immer die finger von. In fertigen programmen füge ich sie dort ein wo eigentlich nie was schiefgehen solle jedoch mal was passieren kann was aber kein Beinbruch ist. Bei Microcontrollern ist das noch krasser, man stelle sich eine Schaltung irgendwo in der pampa vor, da nimmt man lieber einen Wachdog um das Programm zu reseten falls es sich mal aufhäng statt alle halbe Jahre einen Serviceechniker 4h fahren zu lassen um auf den Reset Knopf zu drücken.
Genauso handle ich das das in Programmen.
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

Christian
Beiträge: 6079
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 »

@monta ich bezweifle das das einen performanceunterschied macht der fpc wird in beiden Fällen fast den selben Code erzeugen für ein ry except end saement ist ja auch im normalfall nichtmal zusätzlicher code nötig.
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

monta
Lazarusforum e. V.
Beiträge: 2809
Registriert: Sa 9. Sep 2006, 18:05
OS, Lazarus, FPC: Linux (L trunk FPC trunk)
CPU-Target: 64Bit
Wohnort: Dresden
Kontaktdaten:

Beitrag von monta »

Christian hat geschrieben:@monta ich bezweifle das das einen performanceunterschied macht der fpc wird in beiden Fällen fast den selben Code erzeugen für ein ry except end saement ist ja auch im normalfall nichtmal zusätzlicher code nötig.


Um es mal genauer zu sehen, weils nur ne Vermutung hab, hab ichs mal getestet:

Code: Alles auswählen

procedure TForm1.Button1Click (Sender: TObject );
var x,i:integer;
Tick:Cardinal;
begin
//1.
  x:=0;
  Tick:=GetTickCount;
  try
    for i:=0 to 10000000 do
      inc(x);
  except
  end;
  Memo1.Lines.Add('1.: ' + Inttostr(GetTickCount-Tick));
//2.
  x:=0;
  Tick:=GetTickCount;
  for i:=0 to 10000000 do
    try
      inc(x);
    except
    end;
  Memo1.Lines.Add('2.: ' + Inttostr(GetTickCount-Tick));
//3.
  x:=0;
  Tick:=GetTickCount;
  try
   for i:=0 to 10000000 do
     inc(x);
  except
  end;
  Memo1.Lines.Add('3.: ' + Inttostr(GetTickCount-Tick));
end;


Und mal die Weret für 5 Durchläufe:
1.DL 2.DL 3.DL 4.DL 5.DL Mittel
1. Variante: 31 47 31 46 47 40,4
2. Variante: 234 234 234 235 218 231
3. Variante: 47 32 32 47 47 41


Interessant find ich, das sich die Variante ohne alles und die Variante mit try-Except im Mittel letztlich nicht wirklich unterscheidet.
Johannes

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

Beitrag von theo »

Naja Monta, ich hab das Beispiel doch gemacht, um einen Unterschied aufzuzeigen. Dass man das optimieren kann ist keine Frage.

monta
Lazarusforum e. V.
Beiträge: 2809
Registriert: Sa 9. Sep 2006, 18:05
OS, Lazarus, FPC: Linux (L trunk FPC trunk)
CPU-Target: 64Bit
Wohnort: Dresden
Kontaktdaten:

Beitrag von monta »

theo hat geschrieben:Naja Monta, ich hab das Beispiel doch gemacht, um einen Unterschied aufzuzeigen. Das man das optimieren kann ist keine Frage.


Schon klar, nur ich wollts mal genau wissen, auch weil Christian meinte, es entstett letztlich der selbe Code.

Auf der anderen Seite 190 ms geteilt durch 10 Millionen ist ja auch verschwindend gering, und man sollte ja doch meistens deutlich weniger trys drin haben. Interessant find ich noch Euklids Vergleich mit Ifs.
Johannes

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

Beitrag von theo »

Kommt halt immer drauf an wie und wo man's einsetzt.
Hätte ich bei OpBitmap z.B. um jedes "SetPixel" ein try..except, dann wäre die Bildbearbeitung langsamer. Das macht schon was aus.
Will nur sagen, dass man sich dessen bewusst sein muss, nicht, dass man es nicht einsetzen soll.

Euklid
Lazarusforum e. V.
Beiträge: 2808
Registriert: Fr 22. Sep 2006, 10:38
OS, Lazarus, FPC: Lazarus v2.0.10, FPC 3.2.0
Wohnort: Hessen
Kontaktdaten:

Beitrag von Euklid »

monta hat geschrieben:Auf der anderen Seite 190 ms geteilt durch 10 Millionen ist ja auch verschwindend gering, und man sollte ja doch meistens deutlich weniger trys drin haben. Interessant find ich noch Euklids Vergleich mit Ifs.


Wenn ich deine Tests richtig verstanden habe, lässt sich unter Umständen mittels try-except Zeit sparen. Nämlich dann, wenn der Zeitaufwand für ein Try-except geringer ist als der von If-Anweisungen im zeitkritischen Teil, die tausende mal aufgerufen werden.
Wenn ich das nächste Mal daran programmiere, werde ich mal versuchen, ein Try-Ecept um die gesamte rechenintensive Routine zu legen und Zeiten vergleichen.

John
Beiträge: 273
Registriert: Mo 30. Jul 2007, 19:55

Beitrag von John »

Morgen, wollte euch allen ein gutes Neues Jahr wünschen!

John

Antworten