This is post is simply for fun.
what is the difference between PHP's isset and is_null? Let's see what PHP manual states:
isset: Determine if a variable is set and is not NULL.
is_null: Finds whether the given variable is NULL.
It seems they work for exactly same purpose simply in an opposite way:
$variable = null;
isset($variable) !== is_null($variable)
or
!(isset($variable)) === is_null($variable)
Is that simple? Not really. One difference between isset and is_null is: as its name suggests, when using isset to check an undefined variable, PHP won't raise a NOTICE. But if we use is_null to check an undefined variable, a NOTICE will be raised.
//a NOTICE will be given by PHP
is_null($undefinedVar);
//no NOTICE
isset($undefinedVar);
In PHP manual, there is a note for isset:
Note: Because this (isset) is a language construct and not a function, it cannot be called using variable functions
This tells us isset is a language construct like echo, for, foreach. It is not a function. So here is one difference
//this works
$func = 'is_null';
$func($variable);
//this doesn't work
$func = 'isset';
$func($variable);
Also, is_null is a function, so it can take a function return value as its argument, while isset cannot do that.
//this works
is_null(getVariable());
//this doesn't work
isset(getVariable());
Since isset is language construct while is_null is a function, you can guess there is performance difference between them. Using language construct is more efficient than calling a function. To check the difference, I will use VLD to expose the opcode(about VLD, check this http://hengrui-li.blogspot.com/2011/07/review-php-opcode-with-vld.html)
test1.php
<?php
$name = null;
isset($name);
?>
php -dvld.active=1 test1.php
line # * op fetch ext return operands
---------------------------------------------------------------------------------
2 0 > EXT_STMT
1 ASSIGN !0, null
3 2 EXT_STMT
3 ZEND_ISSET_ISEMPTY_VAR 5 ~1 !0
4 FREE ~1
4 5 > RETURN 1
As we can see, PHP parse isset as one opcode operation: ZEND_ISSET_ISEMPTY_VAR.
test2.php
<?php
$name = null;
is_null($name);
?>
php -dvld.active=1 test2.php
line # * op fetch ext return operands
---------------------------------------------------------------------------------
2 0 > EXT_STMT
1 ASSIGN !0, null
3 2 EXT_STMT
3 EXT_FCALL_BEGIN
4 SEND_VAR !0
5 DO_FCALL 1 'is_null'
6 EXT_FCALL_END
4 7 > RETURN 1
To call a is_null function, PHP does these opcode operations: EXT_FCALL_BEGIN, SEND_VAR, DO_FCALL, EXT_FCALL_END
The result is quite obvious now. isset is more efficient. But sometimes, checking is null simply makes more sense than checking isset, especially when we are checking a function return value:
$name = $user->getName();
isset($name);
is_null($name);
For this example, we can still use isset($user) to check if $user is null or not, but, by the meaning of the name 'isset', here $user seems being set obviously. What we really want to check is if $user is null or not. At this situation(when we simply want to check if a variable is null, not worrying about if it is set), using $name === null is better than using is_null($name)
$name === null returns exactly same result as is_null($name), however, $name === null is more efficient. It is almost as efficient as isset. Let's check the opcode:
test3.php
<?php
$name = null;
$name === null;
?>
php -dvld.active=1 test3.php
line # * op fetch ext return operands
---------------------------------------------------------------------------------
2 0 > EXT_STMT
1 ASSIGN !0, null
3 2 EXT_STMT
3 IS_IDENTICAL ~1 !0, null
4 FREE ~1
4 5 > RETURN 1
From micro performance optimization perspective: isset better than ===null better than is_null.
I think the correct usage of them is: if we want to check if a variable is "set"(or existing), use isset; if we want to check if an existing variable's value is null, use === null.
The performance difference among them belongs to micro-optimization, so i have to run 5 million times of comparison to see the difference:
The performance difference among them belongs to micro-optimization, so i have to run 5 million times of comparison to see the difference:
My testing code is quite simple:
<?php
$counter = 5000000;
$name = 'henry';
$start = microtime(true);
for($i=0; $i<$counter; $i++) {
isset($name);
}
$end = microtime(true);
echo $end - $start, "\n";
?>
?>
I simply replace isset(name) with is_null($name) and $name === null and run the script respectively. And the result is:
isset: 1.62s
===null: 1.80s
is_null: 8.47s
It is a little out of my expect that is_null could be that slower, anyway, just a simple test for fun.
No comments:
Post a Comment