Guide to PHP SecurityQuicksearchCalendar
|
Saturday, March 3. 2012Performance Analysis of isset() vs array_key_exists()At Confoo I had an interesting conversation with Guilherme Blanco regarding the fact that in Doctrine 2 they had a performance issue due to usage of array_key_exists() and how it was significantly slower than isset(). His anecdotal example was that doing isset() took 0.5 seconds, while array_key_exists() for the same operation took 5 seconds! That seemed wrong, given that array_key_exists() simply does a hash table look-up, to determine if the array key exists and the only speed difference would be due to the fact that isset() is a language construct and does not have the overhead of function & parameter processing. So, I've decided to do a quick benchmark using a 5,000 element array. PHP:
<?php
$arr = array();
$fp = fopen("/usr/share/dict/words", "r");
while ($i < 5000 && ($w = fgets($fp))) {
$arr[trim($w)] = ++$i;
}
$s = microtime(1);
for ($i = 0; $i < 100000; $i++) {
isset($arr['abracadabra']);
}
$e = microtime(1);
echo "Isset: ".($e - $s)."\n";
$s = microtime(1);
for ($i = 0; $i < 100000; $i++) {
array_key_exists('abracadabra', $arr);
}
$e = microtime(1);
echo "array_key_exists: ".($e - $s)."\n";
?>
The above benchmark executed on PHP 5.4 shows that while isset() is 2.5 times faster taking a mere 0.0219 seconds vs 0.0549 seconds taken by array_key_exists(), both operations are extremely quick and take a fraction of a second even when doing 100k operations. Any "optimization" between the calls is purely within the super-micro-micro optimization realm and is not going to make any application measurably faster. The bottom line is that if your application does not need to distinguish between an array key that does not exist and one whose value happens to be NULL you should use isset() because it happens to be a little faster. However, if a NULL array key value and a non-existant array key are something you need to differentiate between, use array_key_exists() and you don't need to worry about the performance, the function is extremely fast, even in the case of Doctrine 2 that apparently may do as many as 50,000 calls to the function per-request in some cases. Comments
Display comments as
(Linear | Threaded)
Hi Ilia,
My benchmark was 5s vs 0.5s, not 5m vs 0.5s... =) So it was 10x slower. Cheers, Guilherme Blanco
Fixed the minutes vs seconds, still on 5.4 and 5.3, all I can see is a 2.5 speed difference and both operations are exceptionally fast.
btw, the 10 times hold for 5.3 though. It seems it just got better on 5.4
I ran the code on PHP 5.3.8 and the results were largely the same.
I did the same test today and also tried to mix php ./configuration with --with-debug and --with-maintainer-zts but the result was always really close to the one you published.
But, what could explain guilherme test is if he was using some kind of function traces or profiling in Xdebug. If I do activate one of those I have this result : Isset: 0.032380104064941 array_key_exists: 1.2653131484985 This result is normal since for isset xdebug will not have to keep trace of any function call which is not the case for array_key_exists. It might explain the UGE difference of Guilherme.
hm, of course i have xdebug activated. Maybe this explains it. Another reason to screw microbenchmarks
Hйhй this explain that
Howdy! Someone in my Facebook group shared this site with us so I came to take a look.
I'm definitely enjoying the information. I'm book-marking and will be tweeting this to my followers! Exceptional blog and superb design.
50k calls in one request? What on earth is it doing? It is great to know that PHP 5.4 makes such an improvement though!
PHP 5.3 is a little slower, but not a whole lot, the same code on 5.3 took about the same time to run.
PHP 5.3: Isset: 0.0249950885773 array_key_exists: 0.0579879283905
We noticed this already 9 years ago, granted this was back in PHP 4 days:
https://groups.google.com/forum/?fromgroups#!topic/mailing.www.horde-dev/a5D8ts2D67U It even went into our coding standards: http://www.horde.org/apps/horde/docs/CODING_STANDARDS#existence-checking I have to admit, we never ran a benchmark again, since this made it into our standard. But then again, we didn't have any reason to change what became second nature to us.
funny this comes up now. I specifically called this out as something not to care about in my perf. talk
Do you hear that clicking? It is the sound of 1000s of application writers rewriting their key_exists to issets. Because now it's proven it is 10 times faster! So if my app is slow, it's because of that, not because I do a million of them each function call
Very nice post. I just stumbled upon your weblog and wanted
to say that I've truly enjoyed browsing your blog posts. In any case I'll be subscribing in your rss feed and I am hoping you write once more soon!
I always use this to replace the use of array_key_exists() alone:
if (isset(..) || array_key_exists(...)) { ... } It takes the performance advantage of isset() while keeping the NULL element detected correctly. Detail explanation see this blog post: http://www.zomeoff.com/php-fast-way-to-determine-a-key-elements-existance-in-an-array/
In easytobook we had an edge case of average half a million loop cycles with 3-4 checks per cycle. We saved significant time not just on this example, but also on sacrificing the magic code in favor of public properties and explicit calls.
I was a bit surprized by the fact, so wandered if empty() gives some different results.
At the original test I added the following code: $s = microtime(1); for ($i = 0; $i < 100000; $i++) { empty($arr['abracadabra']); } $e = microtime(1); echo "empty: ".($e - $s)."\n"; The results I got on PHP 5.3.6-13ubuntu3.6 (with XCache v1.3.2, Xdebug v2.1.0, Suhosin v0.9.32.1) isset: 0.05509090423584 array_key_exists: 0.22666001319885 empty: 0.023635864257812 |
ArchivesCategoriesSyndicate This BlogBlog Administration |
|||||||||||||||||||||||||||||||||||||||||||||||||










Comments