At 04:05 29.05.2003, William N. Zanatta said:
[snip]
> It is a known issue that function calls are expensive for the processor.
>
> The OOP let us better organize the code but, thinking in function (or
>method) calls it may be more expensive than in the procedural form.
>
> My question is, has anyone made any tests regarding the performance of
>OOP versus procedural language? Is it a good choice to code in OOP with
>PHP ?
[snip]
Recently we did some research for a decision on how to proceed with a
project - basically the question was should we use objects for tata
storage, or simple associative arrays and a static class handling array nodes.
The testbed source is copied below. The test was run on RH Linux 7.2
running on a Dell Rackmount Server with 2x1GHz, 1GB memory, Apache 1.3.27,
PHP 4.3.2.
The numbers:
3.912186 secs (0.039122 msecs each): Created 10 array entries
0.397721 secs (0.003977 msecs each): Write-Accessed 10 array values
0.364761 secs (0.003648 msecs each): Read-Accessed 10 array values
0.343353 secs (0.003434 msecs each): Deleted 10 array values using
store[idx] = null
0.302970 secs (0.003030 msecs each): Deleted 10 array values using
unset(store[idx])
-
4.880921 secs (0.048809 msecs each): Created 10 object entries
0.492642 secs (0.004926 msecs each): Write-Accessed 10 object values
using direct access
1.148577 secs (0.011486 msecs each): Write-Accessed 10 object values
using access method
0.465929 secs (0.004659 msecs each): Read-Accessed 10 object values
using direct access
0.977031 secs (0.009770 msecs each): Read-Accessed 10 object values
using access method
0.490641 secs (0.004906 msecs each): Deleted 10 object values using
store[idx] = null
0.298719 secs (0.002987 msecs each): Deleted 10 object values using
unset(store[idx])
Comparing the numbers (Array = 100%):
Creating: 124.7%
Write-Access (direct): 123.8%
Write-Access (method): 314.9%
Read-Access (direct): 127.7%
Read-Access (method): 267.9%
Deletion (set to null): 142.9%
Deletion (using unset): 98.5%
For a small number of objects the performance penalty may be minimal.
However if you're dealing with a huge number of instances it may be worth
considering different approaches.
One interesting thing to note is that clearing an array entry using
$array[$idx] = null;
is between 20% - 40% slower than using
unset($array[$idx]);
function measure($start = null, $string = null, $passes = null)
{
$x = microtime();
if ($start) {
list($s0, $s1) = explode(' ', $start);
list($e0, $e1) = explode(' ', $x);
$time = ($e0 + $e1) - ($s0 + $s1);
if ($passes)
$x = sprintf("%f secs (%f msecs each): %s\n",
$time, ($time * 1000) / $passes, $string);
else
$x = sprintf("%f secs: %s\n", $time, $string);
}
return $x;
}
function &make_array()
{
$a = array(
'rid' => null,
'owid' => null,
'pid' => null,
'dcid' => null,
'dsid' => null,
'drid' => null,
'usg' => null,
'rtb' => null,
'idx' => null,
'env' => null,
'xid' => null,
'ci'=> null,
'cr'=> null,
'cd'=> null,
'cts' => null,
'cs'=> null,
'ctx' => null,
'cbl' => null,
);
return $a;
}
class TEST {
var $a;
function TEST() {
$this->a =& make_array();
}
function &access($entry) {
return $this->a[$entry];
}
function set($entry, &$value) {
$this->a[$entry] = $value;
}
}
function runtest($cmd, $text)
{
global $LOOPS;
global $astore;
global $ostore;
$code = <<< EOC
\$x = measure();
for (\$i = 0; \$i < \$LOOPS; ++\$i) $cmd;
echo measure(\$x, "$text");
EOC;
eval($code);
}
function arcopy($x)
{
$a = array();
while (list($k, $v) = each ($x))
$a[$k] = $v;
return $a;
}
$LOOPS = 10;
$astore = array();
$ostore = array();
runtest('$astore[] =& make_array()', 'Created $i array entries');
runtest('$astore[$i]["rid"] = $i', 'Write-Accessed $i array values');
runtest('$n = $astore[$i]["rid"]', 'Read-Accessed $i array values');
$astore2 = arcopy($astore);
runtest('$astore[$i] = null', 'Deleted $i array values using store[idx] =
null');
$astore = $astore2;
runtest('unset($astore[$i])', 'Deleted $i array values using
unset(store[idx])');
echo "-\n";
runtest('$ostore[] = new T