Parsen Leistung (Wenn TryParse, Try-Catch)
Frage
Ich weiß viel über die verschiedenen Möglichkeiten des Umgangs mit Text für Informationen Parsen. Für ganze Zahlen zum Beispiel des Parsen, welche Art von Leistung zu erwarten. Ich frage mich, wenn jemand eine gute Werte auf diese kennt. Ich suche für einige reelle Zahlen von jemandem, der diese getestet hat.
Welche dieser bietet die beste Leistung in welchen Situationen?
Parse(...) // Crash if the case is extremely rare .0001%
If (SomethingIsValid) // Check the value before parsing
Parse(...)
TryParse(...) // Using TryParse
try
{
Parse(...)
}
catch
{
// Catch any thrown exceptions
}
Lösung
Immer T.TryParse (string str, aus T-Wert) . Ausnahmen ist teuer und sollte Werfen vermieden werden, wenn man mit der Situation umgehen können a priori . Mit Hilfe eines Try-Catch-Block zu „retten“ auf die Leistung (weil Ihre ungültige Datenrate niedrig ist) ist ein Missbrauch der Ausnahme auf Kosten der Wartbarkeit Handhabung und gute Programmierpraktiken. Folgen Sie Sound-Software Engineering Entwicklungspraktiken, schreiben Sie Ihre Testfälle, führen Sie Ihre Anwendung, DANN Benchmark und optimieren.
„Wir sollten über kleine Effizienz, sagen sie etwa 97% der Zeit vergessen: vorzeitige Optimierung ist die Wurzel aller Übel Und doch sollten wir unsere Chancen in diesem kritischen 3% nicht verzichten.“ - Donald Knuth
Zu diesem Zweck ordnen Sie, willkürlich wie in Emissionszertifikaten, dass die Leistung von Try-Catch ist schlechter und dass die Leistung von TryParse ist besser . Erst nachdem wir unsere Anwendung und bestimmt ausgeführt haben, dass wir eine Art Verlangsamung w.r.t. haben String-Parsing würden wir sogar überlegen, etwas anderes als TryParse verwendet wird.
(edit: da es der Frages erscheint wollte Zeitdaten mit guten Ratschlägen zu gehen, hier ist die Zeitdaten angefordert)
Die Zeiten für verschiedene Ausfallraten auf 10.000 Eingaben vom Benutzer (für die Ungläubigen):
Failure Rate Try-Catch TryParse Slowdown
0% 00:00:00.0131758 00:00:00.0120421 0.1
10% 00:00:00.1540251 00:00:00.0087699 16.6
20% 00:00:00.2833266 00:00:00.0105229 25.9
30% 00:00:00.4462866 00:00:00.0091487 47.8
40% 00:00:00.6951060 00:00:00.0108980 62.8
50% 00:00:00.7567745 00:00:00.0087065 85.9
60% 00:00:00.7090449 00:00:00.0083365 84.1
70% 00:00:00.8179365 00:00:00.0088809 91.1
80% 00:00:00.9468898 00:00:00.0088562 105.9
90% 00:00:01.0411393 00:00:00.0081040 127.5
100% 00:00:01.1488157 00:00:00.0078877 144.6
/// <param name="errorRate">Rate of errors in user input</param>
/// <returns>Total time taken</returns>
public static TimeSpan TimeTryCatch(double errorRate, int seed, int count)
{
Stopwatch stopwatch = new Stopwatch();
Random random = new Random(seed);
string bad_prefix = @"X";
stopwatch.Start();
for(int ii = 0; ii < count; ++ii)
{
string input = random.Next().ToString();
if (random.NextDouble() < errorRate)
{
input = bad_prefix + input;
}
int value = 0;
try
{
value = Int32.Parse(input);
}
catch(FormatException)
{
value = -1; // we would do something here with a logger perhaps
}
}
stopwatch.Stop();
return stopwatch.Elapsed;
}
/// <param name="errorRate">Rate of errors in user input</param>
/// <returns>Total time taken</returns>
public static TimeSpan TimeTryParse(double errorRate, int seed, int count)
{
Stopwatch stopwatch = new Stopwatch();
Random random = new Random(seed);
string bad_prefix = @"X";
stopwatch.Start();
for(int ii = 0; ii < count; ++ii)
{
string input = random.Next().ToString();
if (random.NextDouble() < errorRate)
{
input = bad_prefix + input;
}
int value = 0;
if (!Int32.TryParse(input, out value))
{
value = -1; // we would do something here with a logger perhaps
}
}
stopwatch.Stop();
return stopwatch.Elapsed;
}
public static void TimeStringParse()
{
double errorRate = 0.1; // 10% of the time our users mess up
int count = 10000; // 10000 entries by a user
TimeSpan trycatch = TimeTryCatch(errorRate, 1, count);
TimeSpan tryparse = TimeTryParse(errorRate, 1, count);
Console.WriteLine("trycatch: {0}", trycatch);
Console.WriteLine("tryparse: {0}", tryparse);
}
Andere Tipps
Auch wenn ich persönlich habe nicht die verschiedenen Möglichkeiten, profiliert, dieser Typ hat:
Try-Catch immer die langsamer. TryParse wird schneller sein.
Die IF und TryParse gleich sind.
Hier ist ein anderer Kerl, der die Leistungsunterschiede ist auch profilierte , und tut dies mit einem paar verschiedenen Datentypen zu sehen, wie viel (wenn überhaupt) sie von Natur aus der Leistung beeinflussen: int, bool, und Datetime.
Option 1: Will throw an exception on bad data.
Option 2: SomethingIsValid() could be quite expensive - particularly if you are pre-checking a string for Integer parsability.
Option 3: I like this. You need a null check afterwards, but it's pretty cheap.
Option 4 is definitely the worst.
Die Ausnahmebehandlung ist vergleichsweise teuer, so vermeiden Sie es, wenn Sie können.
Insbesondere schlechte Eingänge zu erwarten sind, nicht außergewöhnlich, so sollten Sie sie nicht für diese Situation nutzen.
(Obwohl, vor TryParse, kann es die beste Option gewesen sein.)