Schlechte Leistung vieler if-else-Anweisungen in Java

7

Ich habe eine Methode, die alle Kombinationen von fünf verschiedenen Bedingungen mit 32 if-else-Anweisungen überprüft (denken Sie an die Wahrheitstabelle). Die fünf verschiedenen Buchstaben stellen Methoden dar, die jeweils ihre eigenen regulären Ausdrücke in einer Zeichenfolge ausführen und einen booleschen Wert zurückgeben, der angibt, ob die Zeichenfolge mit der Regex übereinstimmt oder nicht. Zum Beispiel:

%Vor%

Es beeinflusst jedoch wirklich die Leistung meiner Anwendung (Entschuldigung, ich kann nicht auf zu viele Details eingehen). Kann jemand einen besseren Weg empfehlen, mit einer solchen Logik umzugehen?

Jede Methode, die einen regulären Ausdruck verwendet, sieht folgendermaßen aus:

%Vor%

Danke!

    
littleK 25.10.2011, 15:09
quelle

10 Antworten

17

Sie können versuchen

%Vor%     
Peter Lawrey 25.10.2011, 15:14
quelle
7

stellt jede Bedingung als ein Bit-Flag dar, testet jede Bedingung einmal und setzt das relevante Flag in einem einzelnen int. dann schalte den int-Wert ein.

%Vor%     
jtahlborn 25.10.2011 15:12
quelle
2

Ohne weitere Details zu kennen, kann es hilfreich sein, die if-Anweisungen so anzuordnen, dass diejenigen, die das "schwere" Heben durchführen, zuletzt ausgeführt werden. Dies macht die Annahme, dass die anderen Bedingungen wahr sind, wodurch die "schweren" anhebenden alle zusammen vermieden werden. Kurz gesagt, nutzen Sie möglichst Kurzschlüsse.

    
tjg184 25.10.2011 15:14
quelle
2

Alle obigen Antworten sind falsch, weil die richtige Antwort auf eine Optimierungsfrage lautet: Messen! Verwenden Sie einen Profiler, um zu messen, wo der Code seine Zeit verbringt.

Nachdem ich das gesagt habe, wäre ich bereit zu wetten, dass der größte Gewinn darin besteht, die Regexe nicht mehr als einmal zu kompilieren. Und danach, wie andere vorgeschlagen haben, nur jede Bedingung einmal bewerten und die Ergebnisse in booleschen Variablen speichern. So hat Thait84 die beste Antwort.

Ich bin auch bereit zu wetten, dass jtahlborn und Peter Lawreys und Salvatore Previti Vorschläge (im Wesentlichen die gleichen), obwohl sie clever sind, Ihnen einen vernachlässigbaren zusätzlichen Nutzen bringen werden, es sei denn, Sie laufen auf einem 6502 ...

(Diese Antwort liest sich wie ich bin voll davon, also im Interesse der vollständigen Offenlegung sollte ich erwähnen, dass ich eigentlich bei der Optimierung hoffnungslos bin. Aber Messen ist immer noch die richtige Antwort.)

    
Andrew Spencer 25.10.2011 15:36
quelle
1

Führe die Regex einmal für jede Zeichenkette aus und speichere die Ergebnisse in booleschen Werten und tue einfach das if / else auf den booleschen Werten, anstatt die regex mehrmals auszuführen. Versuchen Sie außerdem, eine vorkompilierte Version Ihrer Regex erneut zu verwenden und diese erneut zu verwenden, wenn Sie können.

    
thait84 25.10.2011 15:14
quelle
1

Eine mögliche Lösung: Verwenden Sie einen Schalter, der einen Binärwert erzeugt.

%Vor%

Wenn Sie den Schalter umgehen und ein Array verwenden können, wäre es schneller.

    
Salvatore Previti 25.10.2011 15:14
quelle
1

Vielleicht in Schichten partitionieren:

%Vor%

Trotzdem, es fühlt sich an, als müsste es einen besseren Weg dafür geben.

    
G_H 25.10.2011 15:14
quelle
1

Ich habe eine Lösung mit EnumSet. Aber es ist zu ausführlich und ich denke, ich bevorzuge @Peter Lawreys Lösung.

In Effective Java von Bloch wird empfohlen, EnumSet über Bitfelder zu verwenden, aber ich würde hier eine Ausnahme machen. Nichtsdestotrotz postete ich meine Lösung, weil sie für jemanden mit einem etwas anderen Problem nützlich sein könnte.

%Vor%

und du verwendest es so:

%Vor%

Aber es wäre effizienter wie folgt:

%Vor%     
toto2 25.10.2011 15:52
quelle
0

Sie könnten auch Ihren if / else an einen Schalter / Fall anpassen (was ich verstehe, ist schneller)

    
Frank Tudor 25.10.2011 15:13
quelle
0

Vorgenerieren von A, B, C, D und E als boolesche Werte, anstatt sie in if -Bedingungen zu bewerten, würde sowohl Lesbarkeit als auch Leistung bieten. Wenn Sie sich auch Gedanken über die Leistung der verschiedenen Fälle machen, können Sie sie als Baum organisieren oder zu einer einzigen ganzen Zahl kombinieren (X = (A? 1: 0) | (B? 2: 0) | ... | ( E? 16: 0)), die Sie in switch verwenden würden.

    
PypeBros 25.10.2011 15:14
quelle