Frage

Wenn Sie haben die folgenden:

$var = 3; // we'll say it's set to 3 for this example
if ($var == 4) {
    // do something
} else if ($var == 5) {
    // do something
} else if ($var == 2) {
    // do something
} else if ($var == 3) {
    // do something
} else {
    // do something
}

Wenn Sie sagen, 80% der Zeit $var 3, tun Sie sorgen über die Tatsache, dass es sich in 4 Fällen, wenn vor der Suche nach den wahren Fall?

Ich bin am überlegen eine kleine Website, es ist keine große Sache, aber was ist, wenn, dass, wenn die Anweisung ausgeführt wird 1000 mal pro Sekunde?

Ich arbeite in PHP, aber ich dachte, die Sprache spielt dabei keine Rolle.

War es hilfreich?

Lösung

Hier ist, wie wir es Taten, wenn ich zu schreiben-software für radar-Systeme.(Die Geschwindigkeit kommt im radar.Es ist einer der wenigen Orte, wo "Echtzeit" bedeutet eigentlich "real" statt "schnell".)

[I ' ll switch to Python-syntax, es ist einfacher für mich und ich bin sicher, Sie können zu interpretieren.]

if var <= 3:
    if var == 2:
        # do something
    elif var == 3:
        # do something
    else: 
        raise Exception
else:
    if var == 4:
        # do something
    elif var == 5:
        # do something
    else:
        raise Exception

Ihr wenn-Aussagen bilden eine Struktur statt einer flachen Liste.So fügen Sie Bedingungen, die zu dieser Liste, Sie wackeln um die Mitte des Baumes.Die flache Sequenz n Vergleiche durchschnittlich dauert, n/2 Schritte.Der Baum führt zu einer Sequenz von vergleichen, die dauert log(n) Vergleiche.

Andere Tipps

Nun, ich glaube, dass fast die ganze Zeit , die Lesbarkeit von, sagen wir, würde keine winzige Vorteile außer Kraft setzen numerisch geordneten Werten Sie durch die Reduzierung der Anzahl der Vergleichsbefehle gewinnen kann.

Having said that, wie bei allen Optimierungs:

  1. Make it work
  2. Messen Sie
  3. Wenn es schnell genug ist, lassen Sie es allein
  4. Wenn es zu langsam ist, DANN optimieren

Oh, und ich würde wahrscheinlich einen Schalter / Fall aus der Nutzung get-go! ; -)

Ein klassischer Fall, dass dies geschieht (mit buchstäblich 5 Optionen, wie in Ihrem Beitrag) war in ffmpeg, in der decode_cabac_residual Funktion. Das war ziemlich wichtig, da die Profilerstellung (sehr wichtig - optimize dont vor dem Profilieren) zeigte, dass es für mehr als 10-15% der Zeit damit verbracht in H.264 Videodekodierung gezählt. Die if-Anweisung einen Satz von Anweisungen gesteuert, die unterschiedlich für die verschiedenen Typen von Residuen berechnet wurde decodiert werden - und leider zu viel Geschwindigkeit aufgrund Codegröße verloren war, wenn die Funktion 5-mal für jede der fünf Arten von dupliziert wurde Restwert. Anstatt also hatte eine if-Kette verwendet werden.

Profilieren wurde auf viele gemeinsame Testströme getan, um sie in Bezug auf die Wahrscheinlichkeit zu bestellen; die oben war die häufigste, die mindestens die Unterseite. Dies ergab einen kleinen Geschwindigkeitsgewinn.

Nun, in PHP, ich vermute, dass es eine Menge ist weniger von der Low-Level-Stil Geschwindigkeitsverstärkung, die Sie in C bekommen würden, wie im obigen Beispiel.

Mit einem Switch / Case-Anweisung wird das auf jeden Fall den Weg hierher zu gehen.

Dies gibt den Compiler (Interpreter) die Möglichkeit, eine Sprungtabelle zu verwenden, um den rechten Zweig zu erhalten, ohne N Vergleiche zu tun. Denken Sie daran, eine Reihe von Adressen zu schaffen indiziert als 0, 1, 2, .. dann kann es aussehen nur die richtigen oben in der Anordnung in einem einzigen Vorgang.

Plus, da die weniger Syntatic Overhead in einem Fall, Aussage, es liest auch einfacher.

Update: , wenn die Vergleiche für eine switch-Anweisung geeignet sind, dann ist dies ein Bereich, in dem Profil geführt Optimierungen helfen können. Durch den Betrieb des Systems ein PGO bauen mit realistischen Prüfkräften Zweig Nutzungsinformationen erzeugen kann, und dann diese verwenden den Weg genommen zu optimieren.

Anstatt die PHP Frage zu beantworten, werde ich ein bisschen mehr beantworten im Allgemeinen. Es ist nicht direkt anwenden PHP, da es durch eine Art von Interpretation gehen.

Viele Compiler können konvertieren und aus if-elif-elif -... Blöcke Blöcke zu wechseln, wenn nötig, und die Tests in den elif-Teile sind einfach genug (und der Rest der Semantik geschieht kompatibel zu sein). Für 3-4 Tests ist es nicht unbedingt etwas unter Verwendung einer Sprungtabelle zu gewinnen.

Der Grund dafür ist, dass der Zweig-Prädiktor in der CPU bei der Vorhersage, was wirklich gut ist passiert. In der Tat das einzige, was ein wenig höheren Druck auf Anweisung geschieht holen, aber es ist kaum weltbewegend sein wird.

In Ihrem Beispiel würde jedoch die meisten Compiler erkennen, dass $ var eine Konstante 3 und dann $ var mit 3 in der if..elif .. Blöcke ersetzen. Dies wiederum macht die Ausdrücke konstant, so werden sie gefaltet entweder wahr oder falsch. Alle falschen Zweige wird durch die Dead-Code-Eliminator getötet und der Test für wahr ist auch eliminiert. Was bleibt, ist der Fall, wenn $ var == 3. Sie nicht verlassen können auf PHP aber, dass klug zu sein. In der Regel können Sie die Ausbreitung von $ var nicht tun, aber es könnte von einigen Call-Site möglich sein.

Sie könnten versuchen, eine Reihe von Codeblöcken, die Sie in rufen. Dann werden alle Codeblöcke haben den gleichen Aufwand.

Perl 6:

our @code_blocks = (
  { 'Code Block 0' },
  { 'Code Block 1' },
  { 'Code Block 2' },
  { 'Code Block 3' },
  { 'Code Block 4' },
  { 'Code Block 5' },
);

if( 0 <= $var < @code_blocks.length ){
  @code_blocks[$var]->();
}

Wenn der Code zusätzliche Tests zu tun hat, dann wird es sicherlich langsamer laufen. Wenn die Leistung in diesem Abschnitt des Codes kritisch ist, dann sollten Sie den häufigste Fall setzen (en) aus.

Ich bin damit einverstanden normalerweise mit dem „Maß, dann optimieren“ Methode, wenn Sie nicht sicher sind, ob die Leistung schnell genug sein wird, aber wenn der Code muss einfach so schnell wie möglich laufen und die Lösung ist so einfach wie Neuanordnung der Tests, dann würde ich den Code schnell jetzt machen und einige Mess tun, nachdem Sie, dass Ihre Annahme live gehen, um sicherzustellen, (zB, dass 3 80% der Zeit passieren wird) tatsächlich korrekt ist.

Mit Code, wo es ist eine reine Gleichheit Analyse ich es an einen Switch / Fall bewegen würde, so dass eine bessere Leistung bietet.

$var = 3; // we'll say it's set to 3 for this example
switch($var)
 {
   case 4:
      //do something
      break;
   case 5:
      //do something
      break;
   case:
      //do something when none of the provided cases match (same as using an else{ after the elseif{
 }

Jetzt, wenn Ihre kompliziertere Vergleiche tun würde ich entweder Nest sie in dem Schalter, oder einfach nur die elseif verwenden.

In der objektorientierten Sprachen, wenn eine Option massive ifs bietet, dann das bedeutet, Sie sollten nur das Verhalten bewegen (beispielsweise Ihre //do something Blöcke) auf das Objekt den Wert enthält.

Nur können Sie sagen, wenn der Unterschied in der Leistung, die Reihenfolge der Optimierung oder es in der Tat sein, ein binärer Baum neu anordnen, würde einen wesentlichen Unterschied machen. Aber ich vermute, Sie werden Millionen mal pro Sekunde haben, nicht Tausende, sogar über sie in PHP (und mehr noch in einigen anderen Sprachen) Denken zu stören.

Zeit es. Sehen Sie, wie viele Male pro Sekunde Sie die oben laufen kann, wenn / else if / else-Anweisung ohne Maßnahmen getroffen werden und $ var nicht eine der Optionen sein.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top