Thursday, July 30, 2009

PHP Benchmark tests


Share/Bookmark

PHP Benchmark tests

This article is taken from php.lt

NOTE You must keep in mind to refresh this page a few times to "catch" the right result. The numbers change sometimes drastically during each refresh. I assume that this is because of PHP's memory garbage collector that drops in randomly and also other processes that run on this machine have an influence.

Test:
READ LOOP: foreach() vs. while(list()=each())
What is the best way to loop a hash array?
Given is a Hash array with 100 elements, 24byte key and 10k data per entry
I've chosen the large data amount to try out what happens if I reference the data with the &-ref-operator (to avoid copying). But to my surprise the loops are never faster! In tests 5 and 6 are even 10x - 30x slower !! The larger the data entrys are the slower the tests 5 and 6 get! Copying seams always faster then using the &-ref-operator.
Way ???
Let me know at bs_php@users.sourceforge.net
+ 411 %1: foreach($aHash as $val);Total time: 6[ms]
+ 196 %2: while(list(,$val) = each($aHash));Total time: 3[ms]
+ 901 %3: foreach($aHash as $key=>$val);Total time: 14[ms]
+ 938 %4: while(list($key,$val)= each($aHash));Total time: 15[ms]
+ 625 %5: foreach($aHash as $key=>$val) $tmp[] = &$aHash[$key];Total time: 10[ms]
+ 598 %6: while(list($key) = each($aHash)) $tmp[]=&$aHash[$key];Total time: 9[ms]
+ 200 %7: Get key-/ value-array: foreach($aHash as $key[]=>$val[]);Total time: 3[ms]
+ 100 %8: Get key-/ value-array: array_keys() / array_values()Total time: 2[ms]
+ 148 %9: STRANGE: This is the fasetest code when using the the &-ref-operator (to avoid copying)
$key = array_keys($aHash);
$size = sizeOf($key);
for ($i=0; $i<$size; $i++) $tmp[] = &$aHash[$key[$i]];
Total time: 2[ms]
Conclusion:
It must have something to do with PHP4 variable ref-count So you can safely use foreach and only use the &-ref-operator when realy needed OR (according to the link above) when passing objects to functions. (Thanx to Wayne for his help)


Test:
MODIFY LOOP: foreach() vs. while(list()=each())
While the above test only reads and copies the data the question arised what would happen if I modify each value of the hash above.
Again I an unexpected result. Even if I reduce the data size to 100 byte p. e. it ends up that Nr.3 is 1.5 - 2x faster.
+ 602 %1: foreach($aHash as $key=>$val) $aHash[$key] .= "a";Total time: 14[ms]
+ 134 %2: while(list($key) = each($aHash)) $aHash[$key] .= "a";Total time: 3[ms]
+ 100 %3: STRANGE: This is the fasetest code :
$key = array_keys($aHash);
$size = sizeOf($key);
for ($i=0; $i<$size; $i++) $aHash[$key[$i]] .= "a";
Total time: 2[ms]
Conclusion:
Use foreach unless the hash is lage AND has lage data elements. In that case use variation Nr.3 .


Test:
For-loop test
Is it worth the effort to calculate the length of the loop in advance?
E.g. "for ($i=0; $i<$size; $i++)" instead of "for ($i=0; $i
+ 100 %1: With pre calcTotal time: 3[ms]
+ 1021 %2: Without pre calcTotal time: 35[ms]
Conclusion:
The test above speeks for it self. Always calculate the length of the loop in advance!


Test:
Using the &-ref-operator as so called "alias"
Is a good idea to use the &-ref-operator to substitute (or alias) a complex mutidim-array? . Call 1'000x
E.g. $person = &$aHach["country"]["zip"]["streat"]["number"]["name"]
+ 103 %1: NO Aliasing. Using: $aSingleDimArray[$i]Total time: 3[ms]
+ 100 %2: Aliasing. Using: $alias = &$aSingleDimArray[$i]Total time: 3[ms]
+ 147 %3: NO Aliasing. Using: $aMultiDimArray[$i]["aaaaa"]["aaaaaaaaaa"]Total time: 5[ms]
+ 110 %4: Aliasing. Using: $alias = &$aMultiDimArray[$i]["aaaaa"]["aaaaaaaaaa"]Total time: 3[ms]
+ 208 %5: NO Aliasing. Using: veryMultiDimArray[$i]["a"]["aa"]["aaa"]["aaaa"]["aaaaa"]Total time: 7[ms]
+ 126 %6: Aliasing. Using: $alias = &$veryMultiDimArray[$i]["a"]["aa"]["aaa"]["aaaa"]["aaaaa"]Total time: 4[ms]
Conclusion:
It seams to be ok to use aliases. It also makes the code more readabel. But I was expecting to get a lager performance gain; especially with very multdimetional arrays.


Test:
$obj = new SomeClass() vs. $obj =& new SomeClass() using the =&-ref-operator
Is a good idea to use the =&-ref-operator when creating a new object? Call 1'000x
+ 103 %1: $obj = new SomeClass()Total time: 4[ms]
+ 100 %2: $obj =& new SomeClass()Total time: 4[ms]
+ 207 %3: $obj =& $someClass->f();Total time: 8[ms]
+ 135 %4: $obj = $someClass->f();Total time: 6[ms]
Conclusion:
There seams to be no difference in performance.


Test:
double (") vs. single (') quotes
Is a there a difference in using double (") and single (') quotes for strings. Call 1'000x
+ 100 %1: single (') quotes. Just an empty string: $tmp[] = '';Total time: 1[ms]
+ 102 %2: double (") quotes. Just an empty string: $tmp[] = "";Total time: 1[ms]
+ 114 %3: single (') quotes. 20 bytes Text : $tmp[] = 'aaaaaaaaaaaaaaaaaaaa';Total time: 1[ms]
+ 111 %4: double (") quotes. 20 bytes Text : $tmp[] = "aaaaaaaaaaaaaaaaaaaa";Total time: 1[ms]
+ 111 %5: single (') quotes. 20 bytes Text and 3x a $ : $tmp[] = 'aa $ aaaa $ aaaa $ a';Total time: 1[ms]
+ 172 %6: double (") quotes. 20 bytes Text and 3x a $ : $tmp[] = "aa $ aaaa $ aaaa $ a";Total time: 2[ms]
+ 111 %7: double (") quotes. 20 bytes Text and 3x a \$ : $tmp[] = "aa \$ aaaa \$ aaaa \$ a";Total time: 1[ms]
Conclusion:
Single and double quoted strings behave almost the same with one exception: Don't use the a lonely ($) in double quoted string unless you want to reference a PHP-var; or use (\$).


Test:
isSet() vs. empty() vs. is_array()
What is the performance of isSet() and empty(). Call 2'000x
+ 100 %1: isSet() with var that was setTotal time: 1[ms]
+ 101 %2: empty() with var that was setTotal time: 1[ms]
+ 108 %3: isSet() with var that was *not* setTotal time: 1[ms]
+ 101 %4: empty() with var that was *not* setTotal time: 1[ms]
+ 127 %5: isSet() with array-var that was setTotal time: 2[ms]
+ 131 %6: empty() with array-var that was setTotal time: 2[ms]
+ 125 %7: isSet() with array-var that was *not* setTotal time: 2[ms]
+ 126 %8: empty() with array-var that was *not* setTotal time: 2[ms]
+ 140 %9: is_array() of an arrayTotal time: 2[ms]
+ 140 %10: is_array() of a stringTotal time: 2[ms]
+ 343 %11: is_array() of a non set valueTotal time: 4[ms]
+ 115 %12: isSet() AND is_array() of a non set valueTotal time: 1[ms]
Conclusion:
isSet() and empty() are identical. Interesting that a is_array() on a unset val is 3x slower. So alway check if val is set at all befor using type-checking. E.g. if (isSet($foo) AND is_array($foo))


Test:
switch/case vs. if/elseif
Is a there a difference between switch and if elseif. Call 1'000x
+ 131 %1: if and elseif (using ==)Total time: 3[ms]
+ 100 %2: if and elseif (using ===)Total time: 2[ms]
+ 107 %3: caseTotal time: 2[ms]
Conclusion:
Using a switch/case or if/elseif is almost the same. Note that the test is unsing === and is slitly faster then using ==.

1 comment:

  1. Top 10 Most Popular Slots in December 2021 - Drmcd
    In our Top 10 Slots, we 논산 출장안마 have 전라북도 출장샵 a list of the top 10 most 진주 출장마사지 popular slots in December 2021, with 진주 출장안마 our 화성 출장마사지 top 10 most popular slots here.

    ReplyDelete