Какая конструкция быстрее? - PullRequest
0 голосов
/ 22 января 2011

Какая конструкция быстрее:

$a = $b * $c ? $b * $c : 0;  

или

$i = $b * $c;  
$a = $i ? $i : 0;  

Все переменные являются локальными.

Отличается ли скорость для умножения, сложения, вычитания и деления?

Обновление:

Вот некоторые уточнения:

  1. Это теоретический вопрос о написании оптимизированного по скорости кода с нуля. Не о «поиске узких мест».
  2. Я могу измерить скорость кода самостоятельно. Но это был не вопрос домашней работы по использованию microtime (). Это был вопрос о том, как работает PHP-интерпретатор (что я пытался выяснить, копая гугл, но безрезультатно).
  3. Более того - я делал измерения сам с собой и был немного смущен. Различные начальные значения $ a, $ b и $ c (комбинации нулей, отрицательных, положительных, целых чисел и чисел с плавающей точкой) дают разные результаты между конструкциями. Поэтому я растерялся.

BoltClock предоставил мне полезную информацию, но пользователь576875 сделал мой день, разместив ссылку на декодер кода операции! Его ответ содержит также прямой ответ на мой вопрос. Спасибо!

Ответы [ 3 ]

10 голосов
/ 22 января 2011

Если у вас PHP 5.3, это быстрее:

$a = $b * $c ?: 0; 

Это то же самое, что и $a = $b * $c ? $b * $c : 0;, но вычисление $a*$b выполняется только один раз. Кроме того, он не выполняет дополнительных заданий, как в вашем втором решении.

Используя тестовый скрипт Martin v. Löwis, я получаю следующее время:

$a = $b * $c ?: 0;               1.07s
$a = $b * $c ? $b * $c : 0;      1.16s
$i = $b * $c; $a = $i ? $i : 0;  1.39s

Теперь это микрооптимизации, поэтому, возможно, есть много способов оптимизировать ваш код, прежде чем делать это:)

Если это не так, вы также можете сравнить сгенерированные PHP OP-коды:

1 $a = $b * $c ? $b * $c : 0;:

number of ops:  8
compiled vars:  !0 = $a, !1 = $b, !2 = $c
line     #  op                           fetch          ext  return  operands
-------------------------------------------------------------------------------
   1     0  MUL                                              ~0      !1($b), !2($c)
         1  JMPZ                                                     ~0, ->5
         2  MUL                                              ~1      !1($b), !2($c)
         3  QM_ASSIGN                                        ~2      ~1
         4  JMP                                                      ->6
         5  QM_ASSIGN                                        ~2      0
         6  ASSIGN                                                   !0($a), ~2
         7  RETURN                                                   null

2 $i = $b * $c; $a = $i ? $i : 0;

number of ops:  8
compiled vars:  !0 = $i, !1 = $b, !2 = $c, !3 = $a
line     #  op                           fetch          ext  return  operands
-------------------------------------------------------------------------------
   1     0  MUL                                              ~0      !1($b), !2($c)
         1  ASSIGN                                                   !0($i), ~0
         2  JMPZ                                                     !0($i), ->5
         3  QM_ASSIGN                                        ~2      !0($i)
         4  JMP                                                      ->6
         5  QM_ASSIGN                                        ~2      0
         6  ASSIGN                                                   !3($a), ~2
         7  RETURN                                                   null

3 $a = $b * $c ?: 0;:

number of ops:  5
compiled vars:  !0 = $a, !1 = $b, !2 = $c
line     #  op                           fetch          ext  return  operands
-------------------------------------------------------------------------------
   1     0  MUL                                              ~0      !1($b), !2($c)
         1  ZEND_JMP_SET                                     ~1      ~0
         2  QM_ASSIGN                                        ~1      0
         3  ASSIGN                                                   !0($a), ~1
         4  RETURN                                                   null

Эти списки кодов OP были созданы расширением VLD .

1 голос
/ 22 января 2011
<?php
function run(){
$b=10;
$c=10;
$start=gettimeofday(TRUE);
for($k=0;$k<10000000;$k++){
  $a = $b * $c ? $b * $c : 0;  
}
printf("%f\n", gettimeofday(TRUE)-$start);
$start=gettimeofday(TRUE);
for($k=0;$k<10000000;$k++){
  $i = $b * $c;  
  $a = $i ? $i : 0;  
}
printf("%f\n", gettimeofday(TRUE)-$start);
}
run();
?>

В моей системе (PHP 5.3.3, Linux, Core i7 2,8 ГГц) я получаю

1.593521
1.512892

Так что отдельное назначение немного быстрее.Кроме того, (+ вместо *) я получаю обратный результат:

1.386522
1.450358

Так что вам действительно нужно измерить их в вашей собственной системе - с другой версией PHP результат может снова измениться.

0 голосов
/ 22 января 2011

У ваших двух частей кода есть недостаток. Один делает дополнительное задание; другой выполняет дополнительную математическую операцию. Лучше всего этого не делать, что с помощью троичного оператора в PHP 5.3 вы можете:

$a = $b * $c ?: 0;

Если пропустить вторую часть троицы, PHP вместо этого поместит туда результат первой части.

Используя тестовый код Martin v. Löwis, я считаю, что он примерно на 25% быстрее, чем любой из них.

...