Ich mache mir Sorgen um die Leistung meiner Webanwendung und frage mich, welche der "if / else" - oder switch-Anweisungen hinsichtlich der Leistung besser ist.
122
Ich mache mir Sorgen um die Leistung meiner Webanwendung und frage mich, welche der "if / else" - oder switch-Anweisungen hinsichtlich der Leistung besser ist.
if
usw. verwendet werden.Antworten:
Das sind Mikrooptimierung und vorzeitige Optimierung, die böse sind. Sorgen Sie sich lieber um die Lesbarkeit und Wartbarkeit des betreffenden Codes. Wenn mehr als zwei
if/else
Blöcke zusammengeklebt sind oder ihre Größe nicht vorhersehbar ist, können Sie eineswitch
Aussage in Betracht ziehen .Alternativ können Sie auch Polymorphismus greifen . Erstellen Sie zuerst eine Schnittstelle:
Und in einigen Fällen alle Implementierungen in den Griff bekommen
Map
. Sie können dies entweder statisch oder dynamisch tun:Ersetzen Sie schließlich das
if/else
oderswitch
durch etwas Ähnliches (lassen Sie triviale Überprüfungen wie Nullzeiger beiseite):Es ist möglicherweise mikroslower als
if/else
oderswitch
, aber der Code ist zumindest weitaus besser zu warten.Wenn Sie über Webanwendungen sprechen, können Sie diese
HttpServletRequest#getPathInfo()
als Aktionsschlüssel verwenden (schreiben Sie eventuell etwas mehr Code, um den letzten Teil von pathinfo in einer Schleife aufzuteilen, bis eine Aktion gefunden wird). Ähnliche Antworten finden Sie hier:Wenn Sie sich allgemein Gedanken über die Leistung der Java EE-Webanwendung machen, ist dieser Artikel möglicherweise ebenfalls hilfreich. Es gibt andere Bereiche, die einen viel größeren Leistungsgewinn bieten als nur die (Mikro-) Optimierung des Java-Rohcodes.
quelle
Ich stimme voll und ganz der Meinung zu, dass eine vorzeitige Optimierung vermieden werden sollte.
Es stimmt jedoch, dass die Java-VM über spezielle Bytecodes verfügt, die für switch () verwendet werden können.
Siehe WM- Spezifikation ( Lookupswitch und Tableswitch )
Es kann also zu Leistungssteigerungen kommen, wenn der Code Teil des Leistungs-CPU-Diagramms ist.
quelle
Es ist äußerst unwahrscheinlich, dass ein if / else oder ein Switch die Ursache für Ihre Leistungsprobleme sein wird. Wenn Sie Leistungsprobleme haben, sollten Sie zuerst eine Leistungsprofilanalyse durchführen, um festzustellen, wo sich die langsamen Stellen befinden. Vorzeitige Optimierung ist die Wurzel allen Übels!
Trotzdem ist es möglich, mit den Java-Compiler-Optimierungen über die relative Leistung von Switch im Vergleich zu if / else zu sprechen. Beachten Sie zunächst, dass switch-Anweisungen in Java mit einer sehr begrenzten Domäne arbeiten - Ganzzahlen. Im Allgemeinen können Sie eine switch-Anweisung wie folgt anzeigen:
wobei
c_0
,c_1
, ... undc_N
sind ganze Zahlen , die Ziele der switch - Anweisung sind, und<condition>
müssen auf eine ganze Zahl Ausdruck lösen.Wenn diese Menge "dicht" ist, dh (max (c i ) + 1 - min (c i )) / n> α, wobei 0 <k <α <1, wobei
k
größer als ein empirischer Wert ist, a Es kann eine Sprungtabelle erzeugt werden, die sehr effizient ist.Wenn diese Menge nicht sehr dicht ist, aber n> = β, kann ein binärer Suchbaum das Ziel in O (2 * log (n)) finden, was ebenfalls noch effizient ist.
In allen anderen Fällen ist eine switch-Anweisung genauso effizient wie die entsprechende Reihe von if / else-Anweisungen. Die genauen Werte von α und β hängen von einer Reihe von Faktoren ab und werden vom Codeoptimierungsmodul des Compilers bestimmt.
Schließlich
<condition>
ist eine switch-Anweisung natürlich völlig nutzlos , wenn die Domäne von nicht die ganzen Zahlen sind.quelle
Schalter benutzen!
Ich hasse es, wenn-sonst-Blöcke zu pflegen! Habe einen Test:
Mein C # -Standardcode für das Benchmarking
quelle
switch
?Ich erinnere mich, dass ich gelesen habe, dass es im Java-Bytecode zwei Arten von Switch-Anweisungen gibt. (Ich denke, es war in 'Java Performance Tuning'. Eine ist eine sehr schnelle Implementierung, die die Ganzzahlwerte der switch-Anweisung verwendet, um den Offset des auszuführenden Codes zu kennen. Dies würde erfordern, dass alle Ganzzahlen aufeinanderfolgend und in einem genau definierten Bereich sind Ich vermute, dass die Verwendung aller Werte einer Aufzählung auch in diese Kategorie fallen würde.
Ich stimme jedoch vielen anderen Postern zu ... es kann verfrüht sein, sich darüber Sorgen zu machen, es sei denn, dies ist ein sehr, sehr heißer Code.
quelle
switch
verschiedene Methoden, von denen einige effizienter sind als andere. Im Allgemeinen ist die Effizienz nicht schlechter als bei einer einfachen "if
Leiter", aber es gibt genügend Variationen (insbesondere beim JITC), so dass es schwierig ist, viel genauer zu sein.Laut Cliff Click in seinem Java One-Vortrag 2009 Ein Crashkurs in moderner Hardware :
Sie können seine vollständigen Folien hier erhalten .
Cliff gibt ein Beispiel (Abschluss auf Folie 30), das zeigt, dass selbst wenn die CPU Registerumbenennung, Verzweigungsvorhersage und spekulative Ausführung ausführt, sie nur 7 Operationen in 4 Taktzyklen starten kann, bevor sie aufgrund von zwei Cache-Fehlern blockieren muss 300 Taktzyklen, um zurückzukehren.
Um Ihr Programm zu beschleunigen, sollten Sie sich nicht mit solchen kleinen Problemen befassen, sondern mit größeren, z. B. ob Sie unnötige Datenformatkonvertierungen vornehmen, z. B. "SOAP → XML → DOM → SQL → ...". "welches" alle Daten durch den Cache leitet ".
quelle
In meinem Test ist die bessere Leistung unter Windows 7 ENUM> MAP> SWITCH> IF / ELSE IF .
quelle
Time taken for String in Switch :3235 Time taken for String in if/else if :3143 Time taken for String in Map :4194 Time taken for String in ENUM :2866
Für die meisten
switch
und die meistenif-then-else
Blöcke kann ich mir nicht vorstellen, dass es nennenswerte oder signifikante leistungsbezogene Bedenken gibt.Aber hier ist die Sache: Wenn Sie einen
switch
Block verwenden, deutet seine Verwendung darauf hin, dass Sie einen Wert aktivieren, der aus einer Reihe von Konstanten stammt, die zur Kompilierungszeit bekannt sind. In diesem Fall sollten Sie wirklich überhaupt keineswitch
Anweisungen verwenden, wenn Sie eine verwenden könnenenum
mit konstanten spezifischen Methoden verwenden können.Im Vergleich zu einer
switch
Anweisung bietet eine Aufzählung eine bessere Typensicherheit und einen Code, der einfacher zu warten ist. Aufzählungen können so gestaltet werden, dass Ihr Code nicht kompiliert wird, wenn eine Konstante zum Satz von Konstanten hinzugefügt wird, ohne eine konstantenspezifische Methode für den neuen Wert bereitzustellen. Andererseits kann das Vergessen,case
einemswitch
Block einen neuen hinzuzufügen, manchmal nur zur Laufzeit abgefangen werden, wenn Sie das Glück haben, Ihren Block so eingerichtet zu haben, dass eine Ausnahme ausgelöst wird.Die Leistung zwischen
switch
und einerenum
konstantenspezifischen Methode sollte sich nicht wesentlich unterscheiden. Letztere ist jedoch besser lesbar, sicherer und einfacher zu warten.quelle