开发者

Which construction is faster?

Which construction is faster:

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

or

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

All variables are local ones.

Does speed differs for mulitplication, addition, substraction and division?

Update:

Here's some clarification:

  1. This is a theoretical question about writing speed-optimized code from scratch. Not about "searching bottlenecks".
  2. I can measure code speed by myself. But 开发者_开发问答it's was not a question about homework of using microtime(). It was a question about how PHP-interpreter works (what I tried to figure out by digging google myself but was unseccusfull).
  3. Moreover - I did measuring with myself and was a little confused. Different starting values of $a, $b and $c (combinations of zeros, negative, positive, integer and floats) produce different results between constructions. So I was confused.

BoltClock provide me usefull info but user576875 made my day by posting a link to opcode decoder! His answer contains also direct answer to my question. Thanks!


If you have PHP 5.3, this is faster:

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

This is the same as $a = $b * $c ? $b * $c : 0;, but the $a*$b calcultation is done only once. Also, it doesn't do additional assignments as in your second solution.

Using Martin v. Löwis's benchmark script I get the following times:

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

Now these are micro-optimizations, so there is probably many ways of optimizing your code before doing this :)

If it is not the case, you may also want to compare generated PHP OP codes:

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

These OP code listings was generated by the VLD extension.


<?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();
?>

On my system (PHP 5.3.3, Linux, Core i7 2.8GHz), I get

1.593521
1.512892

So the separate assignment is slightly faster. For addition, (+ instead of *), I get the reverse result:

1.386522
1.450358

So you really need to measure these on your own system - with a different PHP version, the outcome may change again.


Your two pieces of code have a drawback each. One does an additional assignment; the other does an additional mathematical operation. Best would be to do neither, which, with the ternary operator in PHP 5.3, you can:

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

Omitting the second part of the ternary causes PHP to put the result of the first part there instead.

Using Martin v. Löwis's benchmarking code, I reckon this is about 25% faster than either.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜