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:
- This is a theoretical question about writing speed-optimized code from scratch. Not about "searching bottlenecks".
- 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).
- 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.
精彩评论