为啥扩展的 ArrayObject 比原始的 ArrayObject 快?

Posted

技术标签:

【中文标题】为啥扩展的 ArrayObject 比原始的 ArrayObject 快?【英文标题】:Why is an extended ArrayObject faster than the original ArrayObject?为什么扩展的 ArrayObject 比原始的 ArrayObject 快? 【发布时间】:2013-12-30 10:36:27 【问题描述】:

首先我找到了这个object vs array,然后 我在代码中添加了一个 ArrayObject 和扩展的 ArrayObject。结果很奇怪:扩展的ArrayObject在计算时间上接近普通的ArrayObject。

这是我的测试用例,数组 vs 对象 vs 数组对象 vs 扩展数组对象:

<pre><?

set_time_limit(0);
$times = 2000;

function profiling($tester, $desc)

    $start = microtime(true);
    $tester();
    echo "$desc: ",(microtime(true) - $start),"\n";


profiling(function()

    global $times;
    for ($i=0; $i<$times; $i++) 
        $z = array();
        for ($j=0; $j<$times; $j++) 
            $z['aaa'] = 'aaa';
            $z['bbb'] = 'bbb';
            $z['ccc'] = $z['aaa'].$z['bbb'];
        
    
, 'use array');


profiling(function()

    global $times;
    for ($i=0; $i<$times; $i++) 
        $z = (object) null;
        for ($j=0; $j<$times; $j++) 
            $z->aaa = 'aaa';
            $z->bbb = 'bbb';
            $z->ccc = $z->aaa.$z->bbb;
        
    
, 'use object');

profiling(function()

    global $times;
    for ($i=0; $i<$times; $i++) 
        $z = new ArrayObject();
        for ($j=0; $j<$times; $j++) 
            $z['aaa'] = 'aaa';
            $z['bbb'] = 'bbb';
            $z['ccc'] = $z['aaa'].$z['bbb'];
        
    
, 'use arrayobject');

profiling(function()

    global $times;
    for ($i=0; $i<$times; $i++) 
        $z = new MyArray();
        for ($j=0; $j<$times; $j++) 
            $z['bbb'] = 'bbb';
            $z['ccc'] = $z['aaa'].$z['bbb'];
        
    
, 'use extends arrayobject');

class MyArray extends  ArrayObject

    function __construct()
    
        parent::__construct(array('aaa'=>'aaa'));
    


echo 'phpversion '.phpversion();

在我的电脑上,输出是

use array: 4.1052348613739
use object: 5.6103208065033
use arrayobject: 5.4503121376038
use extends arrayobject: 4.5252590179443
phpversion 5.3.25

排名为:数组>扩展数组对象>数组对象>对象。

为什么extends ArrayObject 比 ArrayObject 和 Object 快?

【问题讨论】:

【参考方案1】:

这是因为您使用扩展数组对象的函数没有设置 $z['aaa'] 2000 次,但您使用 ArrayObject 的函数是。

如果我添加一个扩展数组对象函数的版本,它确实设置了 $z['aaa'],结果会更加一致:

profiling(function()

    global $times;
    for ($i=0; $i<$times; $i++) 
        $z = new MyArray();
        for ($j=0; $j<$times; $j++) 
            $z['bbb'] = 'bbb';
            $z['ccc'] = $z['aaa'].$z['bbb'];
        
    
, 'use extends arrayobject (no aaa)');

/* added MyArray function with $z['aaa'] = 'aaa' added to the loop */
profiling(function()

    global $times;
    for ($i=0; $i<$times; $i++) 
        $z = new MyArray();
        for ($j=0; $j<$times; $j++) 
            $z['aaa'] = 'aaa';
            $z['bbb'] = 'bbb';
            $z['ccc'] = $z['aaa'].$z['bbb'];
        
    
, 'use extends arrayobject (with aaa)');

输出如下:

use array: 1.3838648796082
use object: 1.9023339748383
use arrayobject: 2.0339980125427
use extends arrayobject (no aaa): 1.6399688720703
use extends arrayobject (with aaa): 2.040415763855
phpversion 5.4.4-14+deb7u7

请注意,在循环中使用 ArrayObject 的函数和使用扩展 ArrayObject 的函数与 $z['aaa'] 的时间更接近。

【讨论】:

以上是关于为啥扩展的 ArrayObject 比原始的 ArrayObject 快?的主要内容,如果未能解决你的问题,请参考以下文章

为啥聚合的 Spark Parquet 文件比原始文件大?

为啥聚合的 Spark Parquet 文件比原始文件大?

为啥神经元网络的隐藏状态不能提供比原始输入更好的降维结果?

Cython:“致命错误:numpy/arrayobject.h:没有这样的文件或目录”

为啥iframe嵌入页面字号比原始页面字号的要小

为啥 NoSQL 比 RDBMS 更擅长“横向扩展”?