What usage of if's is faster? - php

I am quite new to PHP, and I have a question about IF statements.
Example 1:
<?php
if($a == 1){
if($b == 1){
echo 'test';
}
}
?>
Example 2:
<?php
if($a == 1 && $b ==1){
echo 'test';
}
?>
Both have the same result, but which one is faster? Does it even matter?

This is Premature Optimization & Micro Benchmark , you really need to read Don't be STUPID: GRASP SOLID! to understand why i said so
But if you want to know if($a == 1 && $b ==1) seems faster is most PHP versions
See Benchmark
If you want to know the real difference then look at the opcodes
First Code :
line # * op fetch ext return operands
---------------------------------------------------------------------------------
2 0 > IS_EQUAL ~0 !0, 1
1 > JMPZ ~0, ->7
3 2 > IS_EQUAL ~1 !1, 1
3 > JMPZ ~1, ->6
4 4 > ECHO 'test'
5 5 > JMP ->6
6 6 > > JMP ->7
7 > > RETURN 1
Secound Code
line # * op fetch ext return operands
---------------------------------------------------------------------------------
2 0 > IS_EQUAL ~0 !0, 1
1 > JMPZ_EX ~0 ~0, ->4
2 > IS_EQUAL ~1 !1, 1
3 BOOL ~0 ~1
4 > > JMPZ ~0, ->7
3 5 > ECHO 'test'
4 6 > JMP ->7
7 > > RETURN 1
Can you see how similar with very minimal difference. And that is why it does not make sense to worry about this light this but write good and readable code.

They are the same - in both cases if the first condition is false, the second will not be tested.

Both are the same. There are not much code to be optimized you can even write to make shorter syntax.
<?php
echo $a && b ? 'test' : '';
?>
Does the same.
I've modified a bit Baba's benchmark to check the results for shorthand syntax.
Results

Preoptimization is the root to all evil.
That said, your first piece of code is a tiny bit faster (but again, minimally - don't bother to change your code to this - readability is way more important than the tiny speed incremention you get from changing your conditions.
3,000,000 iterations of the first piece of code: ~ 0.9861679077 seconds
3,000,000 iterations of the second piece of code: ~ 1.0684559345 seconds
Difference: ~ 0.0822880268 seconds
Difference per iteration: ~ 0.0000000274 seconds (or 274 nano seconds).

No, it does not matter. Such little performance tweaks are usually overcome by the running environment. Such as inefficient algorithms or client side best practices being ignored.

Both are same, because PHP interpreter is "smart enough" to figure out that.

Related

Is the number the power of 2 - without using log10 ? PHP

I'm new to PHP
I was taking coding challenge and I stumbled on this
piece of code :
// check whether a given positive integer is a power of two.
The solution
function is_Power_of_two($n)
{
if(($n & ($n - 1)) == 0)
{
return "$n is power of 2";
}
else
{
return "$n is not power of 2";
}
}
print_r(is_Power_of_two(4)."\n");
print_r(is_Power_of_two(128)."\n");
print_r(is_Power_of_two(16)."\n");
In the if section, what is happening there ?
let's say $n = 2
2 & 2 - 1 == 0 // replaced $n with num
2 & 1 == 0 ? // results , What ?
EDIT :
So basicly
& isn't a logical operator
It is a bitwise Operator
Bitwise operators allow evaluation and manipulation of specific bits
within an integer.
You can check this video that I found very helpful it will show you how bit's work and how you can work with bitwise
https://www.youtube.com/watch?v=2U-bh4gSn1k
And thanks to : kollol
now I get why the solution code return only the power of two values
Also thanks to :
lars-stegelitz
kiko-software
if both digits are same vertically then the value will be 1, 0 otherwise
for example
2 & 16 = (binary of 2) & (binary of 16)
00010 & 10000
= 00000 = 0
(2) 00010
(16) 10000
------------------
00000
now suppose
2 & 18 = (binary of 2) & (binary of 18)
00010 & 10010
(2) 00010
(18) 10010
----------------------
00010 = not 0
logic is all the numbers which are power of two will always get a 0 in bitwise and operation with 2. Rest will not .

Is it more expensive to set a variable twice or once but inside an else block?

Setting a variable twice
$var = 2;
if ($someThing) {
$var = 1;
}
VS
Using an else
if ($someThing) {
$var = 1;
}
else {
$var = 2;
}
I know that$someThing will get evaluated in both cases. $var Is also going to be set in both cases. In the former it's set once then 50/50 chance to get set again. The later it's set only once, but there's an else block.
I was just curious if anyone has done any sort of testing with something similar. I know this is really micro-optimizing, but just a random thought that I had.
You can look at the opcode steps for each option using the Vulcan Logic Dump
Option #1
compiled vars: !0 = $var, !1 = $someThing
line #* E I O op fetch ext return operands
-------------------------------------------------------------------------------------
3 0 E > ASSIGN !0, 2
4 1 > JMPZ !1, ->3
5 2 > ASSIGN !0, 1
3 > > RETURN 1
Option #2
compiled vars: !0 = $someThing, !1 = $var
line #* E I O op fetch ext return operands
-------------------------------------------------------------------------------------
3 0 E > > JMPZ !0, ->3
4 1 > ASSIGN !1, 1
2 > JMP ->4
7 3 > ASSIGN !1, 2
4 > > RETURN 1
and also using the Ternary operator
compiled vars: !0 = $var, !1 = $someThing
line #* E I O op fetch ext return operands
-------------------------------------------------------------------------------------
3 0 E > > JMPZ !1, ->3
1 > QM_ASSIGN ~2 1
2 > JMP ->4
3 > QM_ASSIGN ~2 2
4 > ASSIGN !0, ~2
5 > RETURN 1
EDIT
As Barmar points out, not all methods execute all the steps, because there are jumps here, and not all steps have an equal processing cost either
It's not about chance whether $someThing is fulfilled, but about the effort the machine has to make. Let's see:
$var = 2;
if ($someThing) {
$var = 1;
}
means min. 1 assignment and 1 check and max. 2 assignments and 1 check.
if ($someThing) {
$var = 1;
}
else {
$var = 2;
}
means min. 1 assignment and 1 check and max. 1 assignment and 1 check.
The else is optimal.
Note: If $someThing depends on $var outside this piece of code and it is called repeatedly and want to be absolutely sure that your code is optimal you'll have to do an amotized cost analysis which isn't too trivial.
You have to imagine it in assembly, which can differ based on architectures.
Here's some basic pseudocode:
write $var 2
bne $something x
write $var 1
x:
or
bne $something x
write $var 1
jmp y:
x:
write $var 2
y:
The first one has an extra write operation sometimes. The second one has an extra jump instruction sometimes. I would think that the jump instruction would be faster, and branch prediction would allow it to be optimised further under the hood, so I'd go for the second option.

Order of precedence with nested ternary operators [duplicate]

This question already has answers here:
Stacking Multiple Ternary Operators in PHP
(11 answers)
Closed 2 years ago.
I was in class the other day and this snippet of code was presented:
<?php
//Intialize the input
$score=rand(50,100);
//Determine the Grade
$grade=($score>=90)?'A':(
($score>=80)?'B':(
($score>=70)?'C':(
($score>=60)?'D':'F')));
//Output the Results
echo "<h1>A score of $score = $grade</h1>";
?>
At the time I questioned the order of operations within the nested ternary operators, thinking that they would evaluate from the inside out, that is it would evaluate if $score were >= 60 first, then if $score >= 70, etc -- working through the whole stack every time regardless of the score.
To me it seems that this construct should follow the same order of precedence given to mathematical operators -- resolving the inner-most set of parentheses first and then working out, unless there is some order of operations unique to the ternary.
Unfortunately the discussion in class quickly became about winning an argument, when I really just wanted to understand how it works. So my questions are two:
(1)How would this statement me interpreted and why?
and
(2)Is the some sort of stack trace or step through tool that would allow me to watch how this code executes?
PHP respects brackets. Expressions inside the innermost ( ... ) are evaluated first, like we are taught in elementary school.
PHP is unusual in that ternary operators are left-associative. This means without brackets, the ternary expression is evaluated left to right.
But in this particular case, the brackets force the expression to be evaluated right to left. This code is equivalent to:
if ($score >= 90) {
$grade = 'A';
}
elseif ($score >= 80) {
$grade = 'B';
}
elseif ($score >= 70) {
$grade = 'C';
}
...
The ternary operator is left associative, but with brackets applied, it evaluates right to left.
You might use xdebug or phpdbg as a step debugger to step through your code and see how it evaluates.
There is also VulcanLogicDumper around, which shows the instructions:
http://3v4l.org/QeF9i/vld#tabs compared to an if-elseif-else structure http://3v4l.org/bZE6M/vld#tabs
line # * op fetch ext return operands
---------------------------------------------------------------------------------
3 0 > SEND_VAL 50
1 SEND_VAL 100
2 DO_FCALL 2 $0 'rand'
3 ASSIGN !0, $0
5 4 IS_SMALLER_OR_EQUAL ~2 90, !0
5 > JMPZ ~2, ->8
6 > QM_ASSIGN ~3 'A'
7 > JMP ->24
6 8 > IS_SMALLER_OR_EQUAL ~4 80, !0
9 > JMPZ ~4, ->12
10 > QM_ASSIGN ~5 'B'
11 > JMP ->23
7 12 > IS_SMALLER_OR_EQUAL ~6 70, !0
13 > JMPZ ~6, ->16
14 > QM_ASSIGN ~7 'C'
15 > JMP ->22
8 16 > IS_SMALLER_OR_EQUAL ~8 60, !0
17 > JMPZ ~8, ->20
18 > QM_ASSIGN ~9 'D'
19 > JMP ->21
20 > QM_ASSIGN ~9 'F'
21 > QM_ASSIGN ~7 ~9
22 > QM_ASSIGN ~5 ~7
23 > QM_ASSIGN ~3 ~5
24 > ASSIGN !1, ~3
10 25 ADD_STRING ~11 '%3Ch1%3EA+score+of+'
26 ADD_VAR ~11 ~11, !0
27 ADD_STRING ~11 ~11, '+%3D+'
28 ADD_VAR ~11 ~11, !1
29 ADD_STRING ~11 ~11, '%3C%2Fh1%3E'
30 ECHO ~11
31 > RETURN 1
How to read these Opcodes
I will try to explain the first JMPZ in the opcode, in order to understand how it evaluates:
Of interest is Line 5, Opcode Number 5:
5 > JMPZ ~2, ->8
This means: If compare with 90 (opcode 4) is false, then JUMP to Opcode 8.
Warning: ->8 doesn't mean jump to Line 8.
Now, what is Opcode 8? The comparison with 80
6 8 > IS_SMALLER_OR_EQUAL ~4 80, !0
And now it's safe to say that this doesn't evaluate, like you expected from inside out (90->60->70), but like an if-elseif-else structure (90->80->70).
The ternary operator short-circuits. Only the appropriate operand is evaluated. This means that the parens do not matter until they are actually tested.
echo false ? (crash() / 0) : "Worked.";
ternary are left to right:
http://php.net/manual/en/language.operators.comparison.php#language.operators.comparison.ternary
So it will evaluate what is to the left of the ? and based on that, evaluate either the 1st or 2nd side of the :.
You could put in a function call that has a side effect to demonstrate this:
function p($a,$b) { echo $a . " >= " . $b; return $a>=$b; }
$grade=(p($score,90))?'A':(
p($score,80)?'B':(
p($score,70)?'C':(
p($score,60)?'D':'F')));

Why this php code output one

I have this php code with me and i am not able to figure it out could anyone help on this.
$x = 3 - 5 % 3;
echo $x;
gives 1 in out put.
Thanks
5 % 3 = 2.
3 - 2 = 1.
There's a specific operator precedence, that causes modulo to be evaluated before minus.
It' s simple math!
% / * operators are first calculated and then
+ -
5 % 3 = 2
3 - 2 = 1
If you want to "prevent" this simply add some brackets:
$x = (3 - 5) % 3;
Of course the answer is correct. PHP parses the code like this 3 - (5 % 3)
5 % 3 is 2 and 3 - 2 gives you 1
5 % 3 is the remainder of 5 /3
It's the order of operations. Without parenthesis around the subtraction, the modulo is being evaluated first. Try this:
$x = (3 - 5) % 3;
echo $x;
% has higher presedence then -. Check out operator precedence
BODMAS - Brackets Order[^] Division Multiplication Addition Substracion .
For,
3 - 5 % 3
first,
5 % 3 gives remainder as 1
second,
3 - 1,
this gives 2.

Understanding PHP op code in a if statement

I'm trying to understand the op code for an simple code.
The code is:
<?php
$a = TRUE;
$b = FALSE;
if($a && $b) {
echo 'done';
}
The op code for the above code is:
php -dvld.active=1 test.php
Finding entry points
Branch analysis from position: 0
Jump found. Position 1 = 3, Position 2 = 4
Branch analysis from position: 3
Jump found. Position 1 = 5, Position 2 = 7
Branch analysis from position: 5
Jump found. Position 1 = 7
Branch analysis from position: 7
Return found
Branch analysis from position: 7
Branch analysis from position: 4
filename: /home/starlays/learning/test.php
function name: (null)
number of ops: 8
compiled vars: !0 = $a, !1 = $b
line # * op fetch ext return operands
---------------------------------------------------------------------------------
3 0 > ASSIGN !0, true
5 1 ASSIGN !1, false
7 2 > JMPZ_EX ~2 !0, ->4
3 > BOOL ~2 !1
4 > > JMPZ ~2, ->7
8 5 > ECHO 'done'
9 6 > JMP ->7
10 7 > > RETURN 1
branch: # 0; line: 3- 7; sop: 0; eop: 2; out1: 3; out2: 4
branch: # 3; line: 7- 7; sop: 3; eop: 3; out1: 4
branch: # 4; line: 7- 7; sop: 4; eop: 4; out1: 5; out2: 7
branch: # 5; line: 8- 9; sop: 5; eop: 6; out1: 7
branch: # 7; line: 10- 10; sop: 7; eop: 7
path #1: 0, 3, 4, 5, 7,
path #2: 0, 3, 4, 7,
path #3: 0, 4, 5, 7,
path #4: 0, 4, 7,
I'm trying to understand what is happening on line 7, how is the evaluation done? How many values does it enter in the expression of if for evaluation? It enters 3 values, or it enters the 2 values the value of $a and value of $b and the expression from the parentheses of if is evaluated afterwards?
I have read the manual for JMPZ_EX, I've understand what is happening in the op code until step 2 after that is a little bit mixed up and it is very hard to me to understand what are exact steps that php is doing.
Another thing that I need to understand is what are all the branches in the op code, which of all that branches will be used at the end?
Unless you are proficient at ASM, I think the easiest way to understand what is happening is looking at the same code by reading its (almost) 1:1 representation in PHP:
if(!$a) goto end;
if(!$b) goto end;
echo 'done';
end: return 0;
The intermediate representation is based on the negations of your actual clauses to make a jump over the code contained in the if block.
If you want to really understand how PHP transforms its input to this opcode array, you'll have to learn about PHP internals, but not before studying the dragon book, particularily the parts about intermediate representation, which is part of the compilation pipeline.
The rest of the opcodes are "background noise", intermediate values, or even one instruction which makes no sense 9 6 > JMP ->7 which simply exists probably because it didn't make sense to put the effort into making the PHP parser spit out the most optimal opcode array for the ZendVM to be run by.
line # * op fetch ext return operands
---------------------------------------------------------------------------------
3 0 > ASSIGN !0, true
5 1 ASSIGN !1, false
7 2 > JMPZ_EX ~2 !0, ->4
3 > BOOL ~2 !1
4 > > JMPZ ~2, ->7
8 5 > ECHO 'done'
9 6 > JMP ->7
10 7 > > RETURN 1
Going by the line numbers #
0 assigns true to !0, !0 is just the internal representation of $A
1 assigns true to !1, !1 is $B
JMPZ means to jump to code if the value is 0. I'm not sure the specific difference of JMPZ_EX it looks like it allows the return of a boolean result.
So:
2 JMPZ_EX, Jump to #4 (->4) if !0 ($A) is 0 (FALSE) and assign the result to ~2
3 BOOL !1 return ~2. ~2 is now equal to the BOOLean value of !1 ($B)
4 JMPZ ~2, Jump to #7 if ~2 is zero
5 ECHO, our echo statement. If any of the JMPZ had jumped, this part would be skipped.
6 JMP -7, jumps to #7
7 RETURN, ends the function call
Some notes:
It seems like the JMPZ_EX is unnecessary in this case, but would be useful in more complex if statements where you need to use the value in calculating further values.
6 JMP -7 is probably in there to allow for an else block. If this was the main part of the if block, finishing it could then jump over the portion of code that was the else block.

Categories