2009-11-25 9 views
18

Ich wiederhole ein Array und sortiere es nach Werten in Wochentage.Was ist schneller: viele Wenns, oder wenn?

Um es zu tun, verwende ich viele if Aussagen. Macht es einen Unterschied für die Verarbeitungsgeschwindigkeit, wenn ich viele if s, im Vergleich zu einer Reihe von else if Anweisungen verwende?

+1

Ich weiß nicht über die Verarbeitungsgeschwindigkeit, aber wenn Sie so viele if Blöcke haben, sollten Sie vielleicht eine switch-Anweisung verwenden. Vor allem für so etwas wie die Tage einer Woche. –

+0

Es gibt eine massive Funktionsänderung, wenn von vielen if-Anweisungen zu einer if-elsaf-Anweisung gewechselt wird. Überlege dir, was dein Code wirklich macht. –

Antwort

41

Ja, ein anderes verwenden, wenn, sollten Sie den folgenden Code ein:

if(predicateA){ 
    //do Stuff 
} 
if(predicateB){ 
    // do more stuff 
} 

von

if(predicateA){ 
    // 
} 
else if(predicateB){ 
    // 
} 

Im zweiten Fall, wenn PrädikatA wahr ist, müssen PrädikatB (und alle weiteren Prädikate) nicht ausgewertet werden (und so wird der gesamte Code schneller ausgeführt), während im ersten Beispiel PrädikatA t ist rue, PrädikatB wird immer noch ausgewertet, und Sie können auch einige unerwartete Überraschungen erhalten, wenn PrädikatA und PrädikatB sich nicht gegenseitig ausschließen.

+1

Es müsste eine erhebliche Anzahl von Bedingungen geben, um tatsächlich einen Leistungsunterschied zu sehen, jedoch +1, als ob sonst sowieso der richtige Weg wäre. – James

+5

Eigentlich ist Ihr Beispiel falsch, weil sie nicht dasselbe tun werden, wenn PredicateA und PredicateB auftreten können. Sie werden nur die erste ausführen und beenden. während der erste Code beide ausführt. –

17

Ich bezweifle, dass eine solche Mikrooptimierung einen messbaren Unterschied in Ihrem Code macht.

Ihr Sortieralgorithmus ist eher die Ursache für ein Leistungsproblem. Welcher Sortieralgorithmus Sie wählen, wird entscheidend sein, nicht viele "Wenns" im Vergleich zu "Anderenfalls".

UPDATE:

Die von anderen gemacht Punkte über „else if“ ist eine bessere Wahl, aufgrund seiner frühzeitigen Ausstieg und exklusive logische Merkmale, lassen vermuten, dass es über „wenn“ in diesem Fall bevorzugt werden sollte.

Aber der Punkt über Algorithmus Wahl steht immer noch - es sei denn, Ihre Daten sind sehr klein.

Es ist offensichtlich, dass O (log n) wäre besser als O (n^2), aber die Größe des Datasets ist auch wichtig. Wenn Sie nur wenige Elemente haben, bemerken Sie den Unterschied möglicherweise nicht. In diesem Fall könnte die Codierung einer ineffizienten Methode in der saubersten, am besten lesbaren, auf den ersten Blick am leichtesten zu verstehen sein.

+5

Die meisten Sortieralgorithmen verwenden verschachtelte Schleifen oder Rekursion und viele Vergleiche zum Sortieren einer gegebenen Menge. Je nachdem, wie viele Vergleiche er in diesem kritischen Teil des Codes durchführt, können vorzeitige Ausgaben und das Überspringen unnötiger Vergleiche zu einer erheblichen Leistungssteigerung führen. –

+1

Einverstanden, guter Punkt, Yannick. – duffymo

+1

Würde ein if-else auch die Lesbarkeit nicht unterstützen und dem Compiler einen anständigen Hinweis geben? –

3

else if wäre schneller in dem Sinne, dass Sie vergleichen, bis Sie eine Bedingung treffen, die zu wahr löst, und Sie den Rest der if s überspringen.

Überlegen Sie auch, die Vergleiche in der Reihenfolge der absteigenden Frequenz neu anzuordnen.

Und verwenden Sie die switch-Anweisung in Abhängigkeit des Datentyps des Objekts, das Sie vergleichen.

Aber an diesem Punkt, wie Duffymo vorgeschlagen hat, würden Sie Mikro-Optimierung sein. Der Leistungsgewinn wird nie so signifikant sein, wenn Sie nicht zuvor den richtigen Sortieralgorithmus für den Job ausgewählt haben.

7

Um ehrlich zu sein, ich glaube nicht, dass es eine Rolle spielen würde, wie Sie es in Bezug auf die Leistung tun, ich bezweifle, dass Sie einen Unterschied sehen würden. Ich würde empfehlen, eine switch-Anweisung verwenden, die keine Leistung enhancment ist, einfach syntaktisch schöner:

switch ($day) 
{ 
    case "Monday": 
     // do something with Monday 
     break; 
    case "Tuesday": 
     // do something with Tuesday 
     break; 
    case "Wednesday": 
     // do something with Wednesday 
     break; 
} 
+0

Ein Switch ist definitiv eine Leistungssteigerung gegenüber vielen Wenns! – Daniel

2

Wenn die Werte ganze Zahlen sind, können Sie eine Optimierung erreichen, indem Sie eine Tabellensuche verwenden. Z.B. Wenn Sie sagen, dass Sie 256 Werte haben, die irgendwie in 7 Tage gemappt werden, könnten Sie ein Array mit 256 Zellen einrichten und jede Zelle enthält den gewünschten Wochentag.Dann statt:


if (value == 0) { 
    dayofweek = 1; 
} else if (value == 1) { 
    dayofweek = 2; 
} else if (value == 2) { 
    dayofweek = 3; 
} else if ... 

.. könnten Sie haben ..


dayofweek = lookuparray[value]; 

Natürlich, wenn Sie diese Technik verwenden, dann sollten Sie die Grenzen der Wert zunächst prüfen.

0

Im Allgemeinen kann "else if" -Stil schneller sein, weil in der Reihe von ifs jede Bedingung nacheinander überprüft wird; Wenn in einer "else if" -Kette eine Bedingung erfüllt ist, wird der Rest umgangen.

Am schnellsten wäre ein Tabellenversand, wofür eine switch-Anweisung optimiert wird, wenn es genügend Fälle gibt (wenn es nur wenige Fälle in einem Switch gibt, wird es in eine Reihe von if-else-Einträgen übersetzt) der resultierende Maschinencode).

0

Die Entscheidung, viele if-Anweisungen oder einen if-elseif-elseif zu verwenden, sollte sich nicht auf die Performance verlassen, da diese Entscheidung den Programmablauf massiv beeinflusst.

Ich bezweifle, dass Sie von vielen If-Anweisungen zu einem großen If-elseif wechseln können, ohne Funktionalität zu verlieren.

Es ist eine Designfrage, keine Leistung.

9

Sie können phpbench einen Blick

Aber um ehrlich zu sein, wenn man auf dieser Ebene optimieren wollen, möchten Sie vielleicht etwas anderes als PHP lernen.

alt text

0

würde ich stattdessen eine andere Stimme in für die Entscheidung für einen Schalter() Anweisung setzen.

2

machte ich eine Benchmark, wenn es zwischen aufeinanderfolgenden if() und if() dann ein paar elseif()

ich eine große Zeichenfolge setzte und habe etwa 20 strpos() jedes Mal (x100 000) ein wahren Unterschied ist mit den beiden Methoden und es zeigte dieses Ergebnis:

Try 1 : 0.5094 (including elseif) 
Try 2 : 0.6700 (including only if) 

Es besteht kein Zweifel. Ich wusste bereits, dass elseif() schneller war, obwohl es eine Rückkehr in der Mitte gibt; Es ist immer noch gut, einige Statistiken in die Antwort einzutragen.

0

Diese Frage ist besonders interessant, wenn der if Block zurückkehrt und damit die Methode beendet. Es gilt auch direkt für die Funktionsweise von Komparatoren in Java.

Ich habe also jede Methode ausgeführt (unten) 250.000.000 Zeiten und die Ergebnisse sind wie folgt:

two values if/else - 6.43 millis 
three values if/else/if - 8.66 millis 
three values if/if  - 9.01 millis 

Während der schlimmsten Fall 1,4 mal länger dauert als die beste Mitteilung machen, dass dies die Gesamtsumme von jeder dieser Methoden 250 Millionen Mal zu wiederholen. Wenn man davon ausgeht, dass ein Mensch 100 ms braucht, um eine Verzögerung wahrzunehmen, und dass der schlimmste/bessere Unterschied 2,58 Millisekunden beträgt, würde dies bedeuten, dass man fast eine Billion (1000 * 1000 Millionen) Iterationen benötigt, um den Unterschied zwischen verschiedenen Methoden zu erkennen.

Fasst it up: Verwendung if-else es ist einer jener Fälle, in denen die schnellste Option mit mehr Lesbarkeit und weniger fehleranfällig auch derjenige ist.

// methods used to measure difference between if and if/else 

/** equality is not important **/ 
private static int comparatorOfIfElse(int a, int b) { 
    if(a < b) return -1; 
    else return 1; 
} 

/** equality is taken into account using if/else **/ 
private static int comparatorOfIfElseIf(int a, int b) { 
    if(a < b) return -1; 
    else if(a > b) return 1; 
    return 0; 
} 

/** equality is taken into account using only if **/ 
private static int comparatorOfIf(int a, int b) { 
    if(a < b) return -1; 
    if(a > b) return 1; 
    return 0; 
} 
Verwandte Themen