Имеет ли значение порядок дел в операторах переключения PHP? - PullRequest
5 голосов
/ 14 июля 2009

В операторах PHP switch повышает ли производительность более распространенные случаи в верхней части списка?

Например, скажем, следующая функция вызывается 1000 раз:

<?php 
function foo_user ($op) {
    switch ($op) {
        case 'after_update':
        //Some Stuff
        case 'login':
        //Some other Stuff
    }
}

Если в 990 из 1000 случаев функция вызывается, то аргумент $ op равен 'login', улучшится ли производительность, если в выражении switch значение case: 'login' выше case 'after_update':? Например, будет ли код после case 'after_update': игнорироваться, если передано $op = login?

Я провел несколько неофициальных тестов по этой идее, но разница была незначительной - возможно, потому что код после case: 'login' и case 'after_update': оба тривиальны. Я бы предпочел не устанавливать более обширный тест с нетривиальными операциями, если кто-то знает ответ прямо.

Это вопрос Drupal, но я думаю, что его может решить любой, кто знаком с оптимизацией PHP.

Ответы [ 4 ]

10 голосов
/ 14 июля 2009

Это, вероятно, будет называться микрооптимизацией. Я не верю, что будет большая разница.

Тем не менее, порядок очень много значит для логики случая переключения, если вы позволите падать случаям, пример

switch ($var) {

    case 0:
    case 1:
       do_it();
       break;
    case 2:
       do_it_else();
       break;

}

Порядок важен, кейс провалится и выполнит любой код, пока не достигнет перерыва.

Меня не беспокоит скорость корпуса переключателя, если бы вы не сказали 100 возможных случаев. Но если тогда, скорее всего, вам следует реорганизовать свой код.

6 голосов
/ 14 июля 2009

Вам понадобится намного больше, чем 1000 случаев, чтобы заметить разницу, но да, есть разница. Я написал тест:

function test_switch($value) {

  $startTime = time() + microtime();

  for ($i = 0; $i < 10000000; $i++) {

    switch($value) {

    case "abcdefg":
      $j = $j + 1;
      break;
    case "hijklmno":
      $j = $j + 1;
      break;
    }
  }

  $endTime = time() + microtime();

  echo "Total time for argument $value: " . ($endTime - $startTime) . "<br>\n";
}

test_switch("abcdefg");
test_switch("hijklmno");

Это 10 миллионов выполнений оператора switch. Выход:

Total time for argument abcdefg: 3.99799704552
Total time for argument hijklmno: 5.38317489624

Так что есть разница, но она не будет заметна, пока вы не достигнете порядка 10 миллионов выполнений, в зависимости от вашего процессора, конечно.

2 голосов
/ 14 июля 2009

Если вы не используете break; для закрытия каждого оператора, PHP продолжит оценивать случаи до конца блока switch, что может повлиять на производительность в достаточно большом блоке. Порядок становится важным для получения поведения, которое вы ищете.

С PHP.Net :

Оператор switch выполняет построчно (фактически оператор за оператором). В начале, код не выполняется. Только когда оператор case найден со значением, совпадающим со значением выражения switch, PHP начинает выполнять операторы. PHP продолжает выполнять операторы до конца блока switch или до того момента, когда он впервые увидит оператор break. Если вы не напишете оператор break в конце списка операторов case, PHP продолжит выполнение операторов следующего дела. Например:

<?php
    switch ($i) {
        case 0:
            echo "i equals 0";
        case 1:
            echo "i equals 1";
        case 2:
            echo "i equals 2";
    }
?>

Я бы предостерег от использования такого поведения и использовал бы break; для каждого case, так как это устранит некоторую двусмысленность при повторном рассмотрении кода позже.

0 голосов
/ 14 июля 2009

Обычно рекомендуется написать наиболее вероятный регистр первый, второй следующий ...

но, как написал Алекс,

Это, вероятно, будет называться микро оптимизация. Я не верю будет большая разница.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...