While optimizing a function in PHP, I changed
if(is_array($obj)) foreach($obj as $key=>$value { [snip] }
else if(is_object($obj)) foreach($obj as $key=>$value { [snip] }
to
if($obj == (array) $obj) foreach($obj as $key=>$value { [snip] }
else if($obj == (obj) $obj) foreach($obj as $key=>$value { [snip] }
After learning about ===
, I changed that to
if($obj === (array) $obj) foreach($obj as $key=>$value { [snip] }
else if($obj === (obj) $obj) foreach($obj as $key=>$value { [snip] }
Changing each test from is_* to casting resulted in a major speedup (>30%).
I understand that ===
is faster than ==
as no coercion has to be done, but why is casting the variable so much faster than calling any of the is_*-functions?
Edit: Since everyone asked about correctness, I wrote this little test:
$foo=(object) array('bar'=>'foo');
$bar=array('bar'=>'foo');
if($foo===(array) $foo) echo '$foo is an array?';
if($bar===(object) $bar) echo '$bar is an object?';
It doesn't print any error and both variables don't get changed, so I think it's working, but I'm ready to be convinced otherwise.
Another Edit: Artefacto's program gives me the following numbers:
PHP 5.3.2-1ubuntu4.2 (64bit) on a Core i5-750 with Xdebug Elapsed (1): 0.46174287796021 / 0.28902506828308 Elapsed (2): 0.52625703811646 / 0.3072669506073 Elapsed (3): 0.57169318199158 / 0.12708187103271 Elapsed (4): 0.51496887207031 / 0.30524897575378 Speculation: Casting and comparing can be about 1.7-4 times faster.
PHP 5.3.2-1ubuntu4.2 (64bit) on a Core i5-750 without Xdebug Elapsed (1): 0.15818405151367 / 0.214271068573 Elapsed (2): 0.1531388759613 / 0.25853085517883 Elapsed (3): 0.16164898872375 / 0.074632883071899 Elapsed (4): 0.14408397674561 / 0.25812387466431 Without Xdebug, the extra function call didn't matter anymore, so every test (except 3) ran faster.
PHP 5.3.2-1ubuntu4.2 on a Pentium M 1.6GHz Elapsed (1): 0.97393798828125 / 0.9062979221344 Elapsed (2): 0.39448714256287 / 0.86932587623596 Elapsed (3): 0.44513893127441 / 0.23662400245667 Elapsed (4): 0.38685202598572 / 0.82854390144348 Speculation: Casting an array is slower, casting an object can be faster, but might not be slower.
PHP 5.2.6-1+lenny8 on a Xeon 5110 Elapsed (1): 0.273758888245 / 0.530702114105 Elapsed (2): 0.276469945908 / 0.605964899063 Elapsed (3): 0.332523107529 / 0.137730836868 Elapsed (4): 0.267735004425 / 0.556323766708 Speculation: These results are similar to Artefacto's results, I think it's PHP 5.2.
The solution: The profiler I used (Xdebug) made function calls about 3 times slower (even when not profiling), but didn't affect casting and comparing noticeably, so casting and comparing appeared to be faster, even though it just wasn't affected by the debugger/profiler.