Showing posts with label php. Show all posts
Showing posts with label php. Show all posts

Monday, September 08, 2008

array_intersect_key is terrible

I always had a hunch that array_intersect_key was slow in PHP, but I didn't quite realize how slow until tonight when I decided to benchmark it. Here's a quick test script:


$big = array();
for ($i = 0; $i < 10000; $i++) {
$big[$i] = 234;
}

$small = array();
for ($i = 0; $i < 10; $i++) {
$big[$i] = 2435;
}

////////////////////////////////////////////////////////////

print "Testing big first\n";

$st = microtime(true);
for ($i = 0; $i < 100; $i++) {
$junk = array_intersect_key($big, $small);
}
$bigfirst = microtime(true) - $st;

////////////////////////////////////////////////////////////

print "Testing small first\n";

$st = microtime(true);
for ($i = 0; $i < 100; $i++) {
$junk = array_intersect_key($small, $big);
}
$smallfirst = microtime(true) - $st;


print "array_intersect_key\n";
print "========================================\n";
print "Big first: $bigfirst\n";
print "Small first: $smallfirst\n";

////////////////////////////////////////////////////////////

function common_keys($a, $b) {
$res = array();
foreach ($a as $key => $val) {
if (isset($b[$key]))
$res[] = $key;
}
return $res;
}

print "Testing big first\n";

$st = microtime(true);
for ($i = 0; $i < 100; $i++) {
$junk = common_keys($big, $small);
}
$bigfirst = microtime(true) - $st;

////////////////////////////////////////////////////////////

print "Testing small first\n";

$st = microtime(true);
for ($i = 0; $i < 100; $i++) {
$junk = common_keys($small, $big);
}
$smallfirst = microtime(true) - $st;

////////////////////////////////////////////////////////////

print "common_keys\n";
print "========================================\n";
print "Big first: $bigfirst\n";
print "Small first: $smallfirst\n";
?>


And the results:


Testing big first
Testing small first
array_intersect_key
========================================
Big first: 13.1110720634
Small first: 12.5442099571
Testing big first
Testing small first
common_keys
========================================
Big first: 0.363513946533
Small first: 0.000243902206421


By implementing this in pure PHP you get a 50000x speedup over using the built-in in some cases. Wow...

Update: this appears to be fixed in PHP 5.2.5. See the Release Notes.

Wednesday, April 09, 2008

PHP Pop Quiz

What would you expect the following code to do?

$foo = 0;
if ($foo == "DB") {
die("hello world");
}
die("goodbye world");
?>


I think most rational people would expect the program to exit with the message "goodbye world."

It turns out that PHP is not so rational. Because $foo is a numeric value, it's compared using a numeric comparator with "DB". This typecast coerces "DB" into an integer value 0, so the equality matches.

The solution, of course, is to use the odd === operator which is unique to PHP. This means something along the lines of "I really mean it. No, seriously!" and disables the coercion of the dissimilar types.

The problem with that method, though, is that "0" === 0 evaluates to false.

Is there a reasonable solution to this?