Neulich bin ich auf einen alten (15.01.2005) Artikel von Jeff Atwood gestoßen. In “Micro-Optimization and Meatballs” testet er verschiedene Methoden zu prüfen ob ein String leer ist. Wie zu erwarten erweist sich hier s.Length == 0 am performantesten:
| |
s.Length == 0 |
s == String.Empty |
s == “” |
s.Equals(String.Empty) |
| 2,4 GHz |
2.6 ms |
20 ms |
20 ms |
13 ms |
| 1,2 GHz |
10 ms |
46 ms |
43 ms |
26 ms |
(Alle Werte gelten für 1 Million Durchläufe einer Schleife, die eine Variable prüft. Die Ausdrücke wurden von mir in C# übersetzt)
Damit endet sein Artikel aber nicht, er schreibt weiter, dass ihm der Vorteil von s.Length == 0 (immerhin 4-5 mal schneller) schlichtweg egal ist. Hier wird die Prüfung 1 000 000 (eine Million) Mal ausgeführt und der Unterschied beträgt beim langsamsten Prozessor maximal 36 Millisekunden. Kann man wagen zu sagen, dass dieser Vorteil also in der Praxis nicht von Bedeutung ist?
Atwood dazu:
Arguments about which method results in code that is easier to read and easier to maintain will be gladly entertained. Arguments about speed will not. Stop micro-optimizing and start macro-optimizing: per Lippert, code that makes sense is code which can be analyzed and maintained, and that makes it performant.
Diese Argumentation kann ich voll unterstützen, sie entspricht auch dem Fazit meines letzten “Tour de Performance”-Artikels, in kurz: Lesbarkeit trumpft geringe Gewinne bei der Performanz.
Eine Kritik in den Kommentaren von Atwoods Artikel war allerdings das Fehlen einer Prüfung gegen NULL. Hier bietet das .NET Framework seit Version 2.0 ja eine praktische Methode. Das hat mich dann doch noch einmal zu einem eigenen Test herausgefordert.
Ich habe drei verschiedene Strings angelegt ...
string s = null;
string t = "";
string u = "value";
... und diese je 1 Million mal geprüft. Folgende drei Tests wurden dabei gemacht:
if (s == null || s.Length == 0)
n++;if (s == null || s == "")
n++;if (string.IsNullOrEmpty(s))
n++;
Für die Tests ergaben sich folgende Zeiten (je für 3 Millionen Durchläufe):
| 1) s == null || s.Length == 0 |
2) s == null || s == “” |
3) string.IsNullOrEmpty(s) |
| 7.28148 ms |
15.69696 ms |
9.14982 ms |
Wieder liegen die Ergebnisse dicht bei einander, besonders 1 und 3, was nicht wundert, denn die Implementierung der IsNullOrEmpty Methode entspricht fast dem Ausdruck von 1.
Daher plädiere ich, überall sowohl auf NULL als auch auf Leerstrings geprüft wird, für die IsNullOrEmpty Methode. Meines Erachtens ist sie am besten lesbar und dabei auch noch sehr performant.