Performance- Problem beim Werfen von Exceptions

Hallo,

ich habe mein Programm so konzipiert, dass ich in bestimmten Fehlersituationen eine eigens definierte Exception werfe, die ich an anderer Stelle auswerte.

throw new ParserException(false, "Nicht unterstützter Befehl: ", (string)cmdParams[cmdParams.Count-1]);
...
catch(ParserException pE){...}

Wenn ich mein Programm frisch gestartet habe und im Programm das erste mal eine Exception geworfen wird, werden ca 1 bis 2 Sekunden (auf nem 3GHz- PC) verbraten. Jedes weitere Werfen der gleichen Exception verbraucht keine erkennbare Zeit. Auch wenn ich mein Programm offen lasse und den Ablauf (Parsen von Dateien), in dem Exceptions geworfen werden neu starte, tritt das Performanceproblem nicht mehr auf.

Dass das Werfen von Exceptions Performanceprobleme verursachen kann, hab ich schon gelesen, aber dass es beim einmaligen Werfen gleich über ne Sekunde verzögert, scheint mir unlogisch. Auch, dass nur beim ersten Werfen Zeit verbraucht wird leuchtet mir nicht ein.

Hat jemand ne Idee, woran das Problem liegen kann, oder wie man eigene Exceptions optimieren kann?

hallo,

ohne dass du schreibst, wie deine exceptions funktionieren kann ich dir nicht helfen.

mir fällt u.a. auf, dass du offensichlich erst zum string castest, und das noch nicht mal als save-cast. verstehe ich nicht, halte ich für gefährlich, wenns um exceptions geht…

wie baust du das array, arbeitest du unter 2005…etc. pp.?

stefan

Hallo Stefan,

ich arbeite mit VS 2003. Mit dem Casten hast du natürlich recht. Ist inzwischen wegoptimiert.

Meine Exception- Klasse ist wie folgt aufgebaut:

 public class ParserException:Exception
 {
 private bool isFailure; // false für Warnung, true für Fehler 
 private string message; // Fehlertext
 private string restOfLine; // Rest der aktuell gelesenen Zeile

 public ParserException(bool isFailure, string message, string restOffLine)
 {
 this.isFailure = isFailure;
 this.message = message;
 this.restOfLine = restOffLine;
 }
 public bool IsFailure
 {
 get
 {
 return isFailure;
 }
 set
 {
 isFailure = value;
 }
 }
 public string Message
 {
 get
 {
 return message;
 }
 set
 {
 message = value;
 }
 }
 public string RestOfLine
 {
 get
 {
 return restOfLine;
 }
 set
 {
 restOfLine = value;
 }
 }
 }

Das Programm läuft so ab, dass ich Strings aus einer Datei ermittle und mir aus diesem String dynamisch Methodennamen zusammenbaue. Diese Methode rufe ich dann per Invoke auf. In einer dieser Methoden wird dann an einer definierten Stelle die eigens definierte Exception per

throw new ParserException(false, "Fehlertext", cmdParams[cmdParams.Length-1]);

geworfen.

Abfangen muss ich dann in meinem Hauptprogramm eine TargetInvocationException deren InnerException meine eigene ParserException ist.
Das erste mal, wenn die Exception geworfen wird, dauerts ca 1 - 2 Sekunden. Bei jedem weiteren Start ist kein Performanceverlust mehr zu merken.

gruß
ziba

Hallo!

Den Effekt, dass die erste geworfene Exception unverhältnismäßig lange dauert, kenne ich auch von .NET 1.1.
Ich wollte es gerade unter .NET 2.0 nachstellen (um etwas auszuprobieren), aber da bekomme ich den Effekt interessanterweise nicht hin - scheinbar wurde hier etwas optimiert.

Was ich ausprobieren wollte (habe gerade kein .NET 1.1 zur Hand), war, ob es jeweils die erste Exception eines Threads oder die erste Exception einer AppDomain ist, die lange dauert.
Wenn letzteres, dann könntest Du einfach irgendwo am Anfang Deiner Anwendung einen Hintergrund-Thread starten, dessen einzige Aufgabe es ist, eine Exception zu werfen (und der Ordnung halber zu fangen).
Dann müssten die weiteren Exceptions in Deiner Anwendung sofort schnell erzeugt werden.

Gruß,
Martin

Hallo Martin,

danke für die Antwort. Ist zwar nicht die sauberste Lösung, funktioniert aber einwandfrei. So merkt der Anwender praktisch nichts vom Performanceverlust. Wenns bei VS 2005 nicht mehr auftritt, ist das wohl noch ein Argument mehr umzusteigen.

gruß
ziba

hallo martin, hallo ziba,

also ich bin ja auch leicht für quick-hacks zu haben…hauptsache es geht…

aber:

bin ich mir nicht sicher, ob hier dezidiert bei .net 2.0 etwas optimiert wurde oder ob das nicht auftreten unter .net2.0 ein seiteneffekt einer anderen vorgehensweise ist (zb. anderer umgang mit threads…).

ich habe mir inzwischen angewöhnt, bei derlei problemen…und wenns nicht nur für mich sondern für kunden ist…der sache mehr auf den grund zu gehen und mich nicht auf die persistente funktion eines quick-hacks zu verlassen. oft sind quick hacks auch die beste grundlage für den bmg-effekt (aber…Bei Mir Gehts).

da ich aber auch nicht weiss woran der effekt liegt, halte ich die klappe und ihr macht was ihr wollt :wink:

stefan

Hi füsigä!

Die Verwendung von Hacks in Produktivcode billige ich ebenso wenig wie Du, aber an der Stelle wurde scheinbar wirklich was von MS geändert.

Mittlerweile hatte ich wieder Zugriff auf ein .NET 1.1-System. Dort in einem Mini-Beispielprogramm eine ApplicationException auf Knopfdruck geworfen und gleich wieder gefangen.
Beim ersten Mal: ca. 2200 ms, jeder weitere Klick auf den Button brachte dann i.d.R.

hallo martin,

hm, also, wie du siehst, ich billge solcherlei vorgehen zwar nicht:wink:, trage aber gerne zur optimierung des hacks bei:

Mit meinem Vorschlag, die erste Exception in einen eigenen
Thread auszulagern, ergeben sich beim Testprogramm aber auch
seltsame Effekte. Wenn ich den anderen Thread im Load-Event
meines Testprogramms starte (oder auch gleich im c’tor des
Forms), dann dauert die Anzeige des Dialogs an sich länger
(ca. um die 2 sek. länger, die die erste Exception sonst
braucht) als ohne separaten Thread…

dann starte den therad wenn Application.Idle geworfen wird…dann sollte man fast nix mehr merken…

Mittlerweile hatte ich wieder Zugriff auf ein .NET 1.1-System.
Dort in einem Mini-Beispielprogramm eine ApplicationException
auf Knopfdruck geworfen und gleich wieder gefangen.
Beim ersten Mal: ca. 2200 ms, jeder weitere Klick auf den
Button brachte dann i.d.R.

http://www.yoda.arachsys.com/csharp/exceptions.html

hallo,

danke für die gute idee. werds gleich mal ausprobieren.

gruß
ziba

Hallo Stefan,

hab die Abfrage des Idle- Events eingebaut. Damit konnte ich erreichen, dass die Applikation sofort aufgeht. Da sie dirket nach dem Start idle ist, wird meine Exception wie gewollt geworfen. Allerdings habe ich jetzt das Problem, dass mein Programm zwar dargestellt wird, aber für die Zeit, die die Exception verbraucht nicht bedienbar ist.

Der ganze Effekt tritt aber nur in der Entwicklungsumgebung auf. Wenn ich die exe aus dem Windows Explorer starte, wird durch die Exception keine Zeit verbraten.

Gruß
ziba