【问题标题】:PHP Objects vs Arrays -- Performance comparison while iteratingPHP 对象与数组——迭代时的性能比较
【发布时间】:2011-01-12 16:15:58
【问题描述】:

我有大量用于神经网络的 PHP 对象,我必须对其进行迭代并执行一些数学运算。我想知道在类的实例上使用关联数组是否会更好?

我正在处理大约 3640 对象并在 500 周围迭代(充其量),因此任何微优化都有很大帮助。使用$object['value'] 会不可避免地比$object->value 更快吗?

编辑:所以它们都是一样的。但我想构造函数会有一点开销?无论哪种方式,我都不认为我想用我漂亮的课程来换取脏数组:P

【问题讨论】:

    标签: php arrays optimization object


    【解决方案1】:

    基于Quazzle的代码,我运行了下一个代码(5.4.16 windows 64bits):

    <?php
    class SomeClass {
        public $aaa;
        public $bbb;
        public $ccc;
        }
    
    function p($i) {
      echo '<pre>';
      print_r($i);
      echo '</pre>';
    }
    
    
    $t0 = microtime(true);
    $arraysOf=array();
    $inicio=memory_get_usage(); 
    for ($i=0; $i<1000; $i++) {
        $z = array();
        for ($j=0; $j<1000; $j++) {
            $z['aaa'] = 'aaa';
            $z['bbb'] = 'bbb';
            $z['ccc'] = $z['aaa'].$z['bbb'];            
        }
        $arraysOf[]=$z;
    }
    $fin=memory_get_usage();    
    echo '<p>arrays: '.(microtime(true) - $t0)."</p>";
    echo '<p>memory: '.($fin-$inicio)."</p>";
    p($z);
    
    $t0 = microtime(true);
    $arraysOf=array();
    $inicio=memory_get_usage(); 
    for ($i=0; $i<1000; $i++) {
        $z = new SomeClass();
        for ($j=0; $j<1000; $j++) {
            $z->aaa = 'aaa';
            $z->bbb = 'bbb';
            $z->ccc = $z->aaa.$z->bbb;          
        }
        $arraysOf[]=$z;
    }
    $fin=memory_get_usage();    
    echo '<p>arrays: '.(microtime(true) - $t0)."</p>";
    echo '<p>memory: '.($fin-$inicio)."</p>";
    p($z);
    
    $t0 = microtime(true);
    $arraysOf=array();
    $inicio=memory_get_usage(); 
    for ($i=0; $i<1000; $i++) {
        $z = new stdClass();
        for ($j=0; $j<1000; $j++) {
            $z->aaa = 'aaa';
            $z->bbb = 'bbb';
            $z->ccc = $z->aaa.$z->bbb;          
        }
        $arraysOf[]=$z;
    }
    $fin=memory_get_usage();    
    echo '<p>arrays: '.(microtime(true) - $t0)."</p>";
    echo '<p>memory: '.($fin-$inicio)."</p>";
    p($z);  
    ?>
    

    我得到了下一个结果:

    arrays: 1.8451430797577
    
    memory: 460416
    
    Array
    (
        [aaa] => aaa
        [bbb] => bbb
        [ccc] => aaabbb
    )
    
    arrays: 1.8294548988342
    
    memory: 275696
    
    SomeClass Object
    (
        [aaa] => aaa
        [bbb] => bbb
        [ccc] => aaabbb
    )
    
    arrays: 2.2577090263367
    
    memory: 483648
    
    stdClass Object
    (
        [aaa] => aaa
        [bbb] => bbb
        [ccc] => aaabbb
    )
    

    php 5.4 的结论

    1. 类比数组快(但略低)。
    2. stdClass 是邪恶的。
    3. 类使用的内存比数组少。 (大约减少 30-40%!)

    ps:作为一个注释,如果类被定义但成员那么,这个类的使用会比较慢。它还使用更多的内存。 显然秘诀是定义成员

    更新

    我从 php 5.4 更新到 php 5.5(5.5.12 x86 windows)。

    arrays: 1.6465699672699
    
    memory: 460400
    
    Array
    (
        [aaa] => aaa
        [bbb] => bbb
        [ccc] => aaabbb
    )
    
    arrays: 1.8687851428986
    
    memory: 363704
    
    SplFixedArray Object
    (
        [0] => aaa
        [1] => bbb
        [2] => aaabbb
    )
    
    arrays: 1.8554251194
    
    memory: 275568
    
    SomeClass Object
    (
        [aaa] => aaa
        [bbb] => bbb
        [ccc] => aaabbb
    )
    
    arrays: 2.0101680755615
    
    memory: 483656
    
    stdClass Object
    (
        [aaa] => aaa
        [bbb] => bbb
        [ccc] => aaabbb
    )
    

    php 5.5 的结论

    1. 对于数组,PHP 5.5 比 PHP 5.4 快,对于对象几乎相同
    2. 由于 PHP 5.5 和数组的优化,类比数组慢。
    3. stdClass 是邪恶的。
    4. 类仍然比数组使用更少的内存。 (大约减少 30-40%!)。
    5. SplFixedArray 与使用 Class 类似,但它使用更多内存。

    【讨论】:

    • 干得好,先生。将其扩展到嵌套数组等会很有趣。其他 PHP 性能的有趣站点:phpbench.comphp-benchmark-script.com 但我喜欢你也使用内存。
    • 在 PHP7 中,数组和对象之间的差异变得更加显着。您的脚本显示 30% 运行时和 60% 内存的差异。那只是我的机器,但根据经验:不要将数组用作结构。改用对象:)
    • 在这种情况下,对象与类不同吗?
    • 添加书签,希望有任何 PHP7 更新。以及可能即将推出的 PHP8,如果适用的话。 @magallanes
    【解决方案2】:

    我将此代码用于“分析”(1000 个实例,1000.000 次读取/写入):

    function p($i) {
      echo '<pre>';
      print_r($i);
      echo '</pre>';
    }
    
    
    $t0 = microtime(true);
    for ($i=0; $i<1000; $i++) {
        $z = array();
        for ($j=0; $j<1000; $j++) {
            $z['aaa'] = 'aaa';
            $z['bbb'] = 'bbb';
            $z['ccc'] = $z['aaa'].$z['bbb'];
        }
    }
    echo '<p>arrays: '.(microtime(true) - $t0);
    p($z);
    
    $t0 = microtime(true);
    for ($i=0; $i<1000; $i++) {
        $z = (object) null;
        for ($j=0; $j<1000; $j++) {
            $z->aaa = 'aaa';
            $z->bbb = 'bbb';
            $z->ccc = $z->aaa.$z->bbb;
        }
    }
    echo '<p>obj: '.(microtime(true) - $t0);
    p($z);
    
    echo '<p> phpversion '.phpversion();
    

    它在我托管这些东西的 LINUX 中输出:

    arrays: 1.1085488796234
    
    Array
    (
        [aaa] => aaa
        [bbb] => bbb
        [ccc] => aaabbb
    )
    obj: 1.2824709415436
    
    stdClass Object
    (
        [aaa] => aaa
        [bbb] => bbb
        [ccc] => aaabbb
    )
    phpversion 5.2.17
    

    总结:即使在 PHP 5.2 上,对象也更慢。除非您确实需要对象的 oop 功能,否则不要使用对象。

    【讨论】:

    • 来自用户 levans stackoverflow.com/users/1473035/levans:我使用 5.3.8 运行此程序,对象速度较慢,数组为 0.51839280128479,对象为 0.85355806350708。我还在 5.4.13 上运行它并得到了相反的结果,可能是由于在 5.4 中进行的类优化,数组的 0.6256799697876 与 0.43650078773499 相比。因此,看起来形势已经发生了逆转,现在是要走的路。
    • 好答案,我刚刚在 XAMPP(Apache) 上进行了测试,得到了以下结果:数组:0.5174868106842 数组 ( [aaa] => aaa [bbb] => bbb [ccc] => aaabbb ) obj : 0.72189617156982 stdClass 对象 ( [aaa] => aaa [bbb] => bbb [ccc] => aaabbb ) phpversion 5.4.19
    • 我也在 5.4.13 上运行,但得到了 Jean-Bernard Pellerin 的相反:数组:0.5020840167999 对象:1.0378720760345 所以我还不会提交对象。
    • 我对代码做了一些更改,并且 Class 比 php 5.4(5.4.16 32bits Windows)的数组快。我提出了一个解释原因的新答案。
    • PHP 5.5.11 结果:数组:0.17430,对象:0.24183
    【解决方案3】:

    magallanes 的脚本 @ PHP 7.3.5

    • SomeClass Object 最快最轻。
    • Array 1.32x 速度。 2.70x 内存。
    • stdClass Object 1.65x 速度。 2.94x​​ 内存。

    原始输出:

    arrays: 0.064794063568115
    memory: 444920
    Array (
        [aaa] => aaa
        [bbb] => bbb
        [ccc] => aaabbb
    )
    arrays: 0.048975944519043
    memory: 164512
    SomeClass Object (
        [aaa] => aaa
        [bbb] => bbb
        [ccc] => aaabbb
    )
    arrays: 0.081161022186279
    memory: 484416
    stdClass Object (
        [aaa] => aaa
        [bbb] => bbb
        [ccc] => aaabbb
    )
    

    【讨论】:

      【解决方案4】:

      好吧,我今天根据@magallanes 基准感到好奇,所以我对其进行了一些扩展。我增加了一些 for 循环以真正突出事物之间的差距。这是在 Apache 2.4、mod_php 和 PHP 7.2 上运行的。

      这是一个汇总表,可以让结果更容易:

      +---------------------------+---------+-----------------+
      |           Test            | Memory  |      Time       |
      +---------------------------+---------+-----------------+
      | Array                     | 2305848 | 9.5637300014496 |
      | stdClass                  | 2505824 | 11.212271928787 |
      | SomeClass                 |  963640 | 11.558017015457 | <-- *
      | AnotherClass              | 2563136 | 10.872401237488 |
      | SetterClass               |  905848 | 59.879059791565 |
      | SetterClassDefineReturn   |  905792 | 60.484427213669 |
      | SetterClassSetFromParam   |  745792 | 62.783381223679 |
      | SetterClassSetKeyAndParam |  745824 | 72.155715942383 |
      +---------------------------+---------+-----------------+
      * - Winner winner chicken dinner
      

      以下是修改后的脚本。我想用方法和定义类型来测试设置属性。我很惊讶地发现使用 setter 方法会显着增加代码的影响。现在承认这是一个非常非常具体的性能测试,许多应用程序甚至都不会达到这个目标。但是,如果您的网站处理 1000/reqs/秒的 1000 个类与 1000 个对象一起使用,您可以看到这可能如何影响性能。

      <?php
      
      set_time_limit(500);
      
      class SomeClass {
          public $aaa;
          public $bbb;
          public $ccc;
      }
          
      class AnotherClass {
      }
      
      class SetterClass {
          public $aaa;
          public $bbb;
          public $ccc;
      
          public function setAAA() {
              $this->aaa = 'aaa';
          }
      
          public function setBBB() {
              $this->bbb = 'bbb';
          }
      
          public function setCCC() {
              $this->ccc = $this->aaa.$this->bbb;
          }
      }
      
      class SetterClassDefineReturn {
          public $aaa;
          public $bbb;
          public $ccc;
      
          public function setAAA():void {
              $this->aaa = 'aaa';
          }
      
          public function setBBB():void {
              $this->bbb = 'bbb';
          }
      
          public function setCCC():void {
              $this->ccc = $this->aaa.$this->bbb;
          }
      }
      
      class SetterClassSetFromParam {
          public $aaa;
          public $bbb;
          public $ccc;
      
          public function setAAA(string $val): void {
              $this->aaa = $val;
          }
      
          public function setBBB(string $val): void {
              $this->bbb = $val;
          }
      
          public function setCCC(string $val): void {
              $this->ccc = $val;
          }
      }
      
      class SetterClassSetKeyAndParam {
          public $aaa;
          public $bbb;
          public $ccc;
      
          public function set(string $key, string $val): void {
              $this->{$key} = $val;
          }
      }
      
      function p($i) {
        echo '<pre>';
        print_r($i);
        echo '</pre>';
        echo '<hr>';
      }
      
      $t0 = microtime(true);
      $arraysOf=[];
      $inicio=memory_get_usage(); 
      for ($i=0; $i<5000; $i++) {
          $z = new SomeClass();
          for ($j=0; $j<5000; $j++) {
              $z->aaa = 'aaa';
              $z->bbb = 'bbb';
              $z->ccc = $z->aaa.$z->bbb;          
          }
          $arraysOf[]=$z;
      }
      $fin=memory_get_usage();    
      echo '<p>Time Taken (seconds): '.(microtime(true) - $t0).'</p>';
      echo '<p>Memory: '.($fin-$inicio).'</p>';
      p($z);
      
      $t0 = microtime(true);
      $arraysOf=[];
      $inicio=memory_get_usage(); 
      for ($i=0; $i<5000; $i++) {
          $z = new AnotherClass();
          for ($j=0; $j<5000; $j++) {
              $z->aaa = 'aaa';
              $z->bbb = 'bbb';
              $z->ccc = $z->aaa.$z->bbb;          
          }
          $arraysOf[]=$z;
      }
      $fin=memory_get_usage();    
      echo '<p>Time Taken (seconds): '.(microtime(true) - $t0).'</p>';
      echo '<p>Memory: '.($fin-$inicio).'</p>';
      p($z);
      
      $t0 = microtime(true);
      $arraysOf=[];
      $inicio=memory_get_usage(); 
      for ($i=0; $i<5000; $i++) {
          $z = new SetterClass();
          for ($j=0; $j<5000; $j++) {
              $z->setAAA();
              $z->setBBB();
              $z->setCCC();          
          }
          $arraysOf[]=$z;
      }
      $fin=memory_get_usage();    
      echo '<p>Time Taken (seconds): '.(microtime(true) - $t0).'</p>';
      echo '<p>Memory: '.($fin-$inicio).'</p>';
      p($z);
      
      $t0 = microtime(true);
      $arraysOf=[];
      $inicio=memory_get_usage(); 
      for ($i=0; $i<5000; $i++) {
          $z = new SetterClassDefineReturn();
          for ($j=0; $j<5000; $j++) {
              $z->setAAA();
              $z->setBBB();
              $z->setCCC();          
          }
          $arraysOf[]=$z;
      }
      $fin=memory_get_usage();    
      echo '<p>Time Taken (seconds): '.(microtime(true) - $t0).'</p>';
      echo '<p>Memory: '.($fin-$inicio).'</p>';
      p($z);
      
      $t0 = microtime(true);
      $arraysOf=[];
      $inicio=memory_get_usage(); 
      for ($i=0; $i<5000; $i++) {
          $z = new SetterClassSetFromParam();
          for ($j=0; $j<5000; $j++) {
              $z->setAAA('aaa');
              $z->setBBB('bbb');
              $z->setCCC('aaabbb');          
          }
          $arraysOf[]=$z;
      }
      $fin=memory_get_usage();    
      echo '<p>Time Taken (seconds): '.(microtime(true) - $t0).'</p>';
      echo '<p>Memory: '.($fin-$inicio).'</p>';
      
      p($z);
      
      $t0 = microtime(true);
      $arraysOf=[];
      $inicio=memory_get_usage(); 
      for ($i=0; $i<5000; $i++) {
          $z = new SetterClassSetKeyAndParam();
          for ($j=0; $j<5000; $j++) {
              $z->set('aaa', 'aaa');
              $z->set('bbb', 'bbb');  
              $z->set('ccc', 'aaabbb');        
          }
          $arraysOf[]=$z;
      }
      $fin=memory_get_usage();    
      echo '<p>Time Taken (seconds): '.(microtime(true) - $t0).'</p>';
      echo '<p>Memory: '.($fin-$inicio).'</p>';
      p($z);
      
      $t0 = microtime(true);
      $arraysOf=[];
      $inicio=memory_get_usage(); 
      for ($i=0; $i<5000; $i++) {
          $z = new stdClass();
          for ($j=0; $j<5000; $j++) {
              $z->aaa = 'aaa';
              $z->bbb = 'bbb';
              $z->ccc = $z->aaa.$z->bbb;          
          }
          $arraysOf[]=$z;
      }
      $fin=memory_get_usage();    
      echo '<p>Time Taken (seconds): '.(microtime(true) - $t0).'</p>';
      echo '<p>Memory: '.($fin-$inicio).'</p>';
      p($z); 
      
      
      $t0 = microtime(true);
      $arraysOf=[];
      $inicio=memory_get_usage(); 
      for ($i=0; $i<5000; $i++) {
          $z = [];
          for ($j=0; $j<5000; $j++) {
              $z['aaa'] = 'aaa';
              $z['bbb'] = 'bbb';
              $z['ccc'] = $z['aaa'].$z['bbb'];            
          }
          $arraysOf[]=$z;
      }
      $fin=memory_get_usage();    
      echo '<p>Time Taken (seconds): '.(microtime(true) - $t0).'</p>';
      echo '<p>Memory: '.($fin-$inicio).'</p>';
      p($z);
      

      结果如下:

      Time Taken (seconds): 11.558017015457
      
      Memory: 963640
      
      SomeClass Object
      (
          [aaa] => aaa
          [bbb] => bbb
          [ccc] => aaabbb
      )
      
      -----
      
      Time Taken (seconds): 10.872401237488
      
      Memory: 2563136
      
      AnotherClass Object
      (
          [aaa] => aaa
          [bbb] => bbb
          [ccc] => aaabbb
      )
      
      ----
      
      Time Taken (seconds): 59.879059791565
      
      Memory: 905848
      
      SetterClass Object
      (
          [aaa] => aaa
          [bbb] => bbb
          [ccc] => aaabbb
      )
      
      ----
      
      Time Taken (seconds): 60.484427213669
      
      Memory: 905792
      
      SetterClassDefineReturn Object
      (
          [aaa] => aaa
          [bbb] => bbb
          [ccc] => aaabbb
      )
      
      ----
      
      Time Taken (seconds): 62.783381223679
      
      Memory: 745792
      
      SetterClassSetFromParam Object
      (
          [aaa] => aaa
          [bbb] => bbb
          [ccc] => aaabbb
      )
      
      ----
      
      Time Taken (seconds): 72.155715942383
      
      Memory: 745824
      
      SetterClassSetKeyAndParam Object
      (
          [aaa] => aaa
          [bbb] => bbb
          [ccc] => aaabbb
      )
      
      ----
      
      Time Taken (seconds): 11.212271928787
      
      Memory: 2505824
      
      stdClass Object
      (
          [aaa] => aaa
          [bbb] => bbb
          [ccc] => aaabbb
      )
      
      ----
      
      Time Taken (seconds): 9.5637300014496
      
      Memory: 2305848
      
      Array
      (
          [aaa] => aaa
          [bbb] => bbb
          [ccc] => aaabbb
      )
      
      

      【讨论】:

        【解决方案5】:

        我在 php 7.0.9 下使用 magallanes 的代码:

        arrays: 0.19802498817444
        
        memory: 324672
        
        Array
        (
            [aaa] => aaa
            [bbb] => bbb
            [ccc] => aaabbb
        )
        arrays: 0.18602299690247
        
        memory: 132376
        
        SomeClass Object
        (
            [aaa] => aaa
            [bbb] => bbb
            [ccc] => aaabbb
        )
        arrays: 0.1950249671936
        
        memory: 348296
        
        stdClass Object
        (
            [aaa] => aaa
            [bbb] => bbb
            [ccc] => aaabbb
        )
        

        和用户php 7.1.3:

        arrays: 0.59932994842529
        memory: 444920
        Array
        (
            [aaa] => aaa
            [bbb] => bbb
            [ccc] => aaabbb
        )
        
        arrays: 0.72895789146423
        memory: 164512
        
        SomeClass Object
        (
            [aaa] => aaa
            [bbb] => bbb
            [ccc] => aaabbb
        )
        
        arrays: 0.61777496337891
        memory: 484416
        stdClass Object
        (
            [aaa] => aaa
            [bbb] => bbb
            [ccc] => aaabbb
        )                      
        

        【讨论】:

        • 别忘了 stdClass 可以使用真正的字符串数字键。 ['1'=>1] 将存储为 [1=>1],但我们可以使用 $a=new stdClass(); $a-&gt;{1} = 1; $b=(array)$a; 获取真实的 ['1'=>1]。
        • 所以,总而言之.. 数组的速度提高了 18%,但消耗的内存是原来的 2.7 倍。
        【解决方案6】:

        对于仍然对此问题感兴趣的任何人:) 我在 PHP 7.1 Ubuntu x64 上运行了 Quazzle 代码并得到了这个答案:

        arrays: 0.24848890304565
        
        memory: 444920
        
        Array
        (
            [aaa] => aaa
            [bbb] => bbb
            [ccc] => aaabbb
        )
        arrays: 0.23238587379456
        
        memory: 164512
        
        SomeClass Object
        (
            [aaa] => aaa
            [bbb] => bbb
            [ccc] => aaabbb
        )
        arrays: 0.24422693252563
        
        memory: 484416
        
        stdClass Object
        (
            [aaa] => aaa
            [bbb] => bbb
            [ccc] => aaabbb
        )
        

        结论

        数组比类对象占用4(!)内存。
        类对象稍微快一点。
        stdClass 仍然邪恶 © magallanes :)

        【讨论】:

        • 动态添加的属性在内存方面与数组没有太大区别。但是纯数据结构(声明的公共字段,非动态)的内存效率更高。我徘徊如果您使用 SomeClass 并删除 public $ccc 并让它动态声明会发生什么,它将占用与 AnotherClass 相同的内存。
        【解决方案7】:

        您还没有向我们展示 $object-&gt;value 如何工作的代码,因为后端可能是一个数组,在这种情况下理论上使用数组会更快,因为它涉及的更少函数调用。与函数调用相比,查找的成本可能会很大。如果它是一个变量,则差异会很小,因为 PHP 中的对象和数组具有非常相似的实现。

        如果您正在考虑优化,则需要进行分析以检查大部分时间都在哪里使用。我怀疑将对象更改为数组不会产生重大影响。

        【讨论】:

        • 我假设该值将是一个公共变量,因此肯定是 O(1) 而哈希查找可能不是。
        【解决方案8】:

        我看到这是一篇旧帖子,所以我想我会更新它。 这是我在 Zend CE 5.3.21 上完成的代码和统计信息 我试图测试整个事情,存储信息并将其拉回。

        V1:耗时 0.83 秒

        for ($i=1; $i<1000000; $i++) {
          $a = get_one();
          $b = $a[0];
          $b = $a[1];
        }
        
        function get_one() {
          return array(1,1);
        }
        

        V2:耗时 3.05 秒

        for ($i=1; $i<1000000; $i++) {
          $a = get_one();
          $b = $a->v;
          $b = $a->k;
        }
        
        function get_one() {
          $ret = new test();
          $ret->v = 1;
          $reb->k = 1;
          return $ret;
        }
        
        class test {
          public $v;
          public $k;
        }
        

        V3 : 耗时 1.98 秒(注意构造函数提高了性能)

        for ($i=1; $i<1000000; $i++) {
          $a = get_one();
          $b = $a->v;
          $b = $a->k;
        }
        
        function get_one() {
          return new test(1,1);
        }
        
        class test {
          public $v;
          public $k;
          public function __construct($v, $k) {
            $this->v = $v;
            $this->k = $k;
          }
        }
        

        【讨论】:

          【解决方案9】:

          您可以随时查看 PHP 源代码中的微性能特性。

          但乍一看,不做 ['value'] 不会更快,因为 PHP 需要查找在哪里找到 ['value'] 即使哈希表查找应该是 O(1),那不是保证。使用 Text-index 会产生更多开销。

          如果对象仅包含 1 个您需要访问的变量,即值,则使用对象会产生更多开销。

          【讨论】:

          • 您认为属性是在哪里查找的?它们也在哈希表中......(尽管这在主干中或多或少是正确的)。
          【解决方案10】:

          如果数组和类的性能一样,我认为使用预定义类的对象来存储/传递业务数据会使我们的程序更具逻辑性,代码更具可读性。

          今天,有了像 Eclipse、Netbean 这样的现代 ide……知道(预定义类的)对象携带什么信息非常方便,但数组却不是这样

          例如: 带数组

          function registerCourse(array $student) {
              // Right here I don't know how a $student look like unless doing a print_r() or var_dump()
           ....
          }
          

          有对象

          class Studen {
              private $_name, $_age;
              public function getAge() {}
              public function getName() {}
              ..
          }
          
          function registerCourse(Studen $student) {
              // Right here I just Ctrl+Space $student or click "Student" and I know I can get name or age from it
              ...
          }
          

          【讨论】:

          • 这与其他经过验证的答案相矛盾,并且没有证据。所以这更像是一种意识形态信念,而不是实际答案。
          【解决方案11】:

          公平地说,这取决于您拥有什么样的数据。其他答案的结果(或多或少)*正确。为了清楚起见,我将在底部粘贴测试代码。

          这里重要的是,如果您使用预定义的对象,您可以节省相当多的内存,权衡是您需要定义确切的结构。

          考虑以下测试结果:

          static obj: 0.04223108291626
          memory: 164920
          object(staticSet)#1 (3) {
            ["aaa"]=>
            string(3) "aaa"
            ["bbb"]=>
            string(3) "bbb"
            ["ccc"]=>
            string(6) "aaabbb"
          }
          ---------------------------------------
          static obj with an additional prop: 0.042968988418579
          memory: 524920
          object(staticSet2)#1000 (3) {
            ["aaa"]=>
            string(3) "aaa"
            ["bbb"]=>
            string(3) "bbb"
            ["ddd"]=>
            string(6) "aaabbb"
          }
          ---------------------------------------
          

          我在这里可能错了,我没有查看 PHP 源代码,但我相信就 PHP 而言,一切都是数组。预定义的对象只是一个定义良好的数组。一个有趣的说明是值类型没有效果,即。字符串值 '1' 将占用与布尔值 true 相同的内存量。

          为什么?正如我之前所说,PHP 是数组,所以如果你有一个带有 setter 函数的对象(简化版),PHP 的作用是:

          $objects = ['objectName' => [
              'aaa' => '',
              'bbb' => '',
              'ccc' => '',
              'setValue:f' => function('name', 'value') { ... }
              ]
          ];
          

          每次执行时,都会查找用于查找道具名称的功能键,以及在后台对道具类型等进行任何验证。预定义对象中的内存节省来自于定义一个设定长度的数组(否则在 PHP 中是不可能的),而不是分配一块内存。

          结论:

          静态对象:耶!我们节省内存!但是如果你尝试在定义之外添加任何东西,它会变得比 stdClass 更大。

          ['aaa'] into [['aaa'],['bbb']]
          

          数组:如果你用 PHP 编写你最好喜欢它们,即使是字符串也是 PHP 中的字符数组。

          对象:对象具有很酷的功能,它们是保持代码有条理、干净、模块化的好方法。但众所周知,“拥有强大的力量……”。

          最后,我的测试代码和“*”。人们似乎忘记了,如果您在脚本运行时不清理变量,它们将保留在内存中,虽然它不会影响执行时间(很多),但会影响内存测量。所以在运行内存分析时 unset() 是你的朋友。

          <?php
          
          error_reporting(E_ALL);
          ini_set('display_errors',1);
          
          $noOfObjects = 1000;
          $noOfOperations = 1000;
          
          class set {
              public function setKey($key, $value) {
                  $this->{$key} = $value;
              }
              public function readKey($name) {
                  return $this->{$name};
              }
          }
          
          class staticSet {
              public string $aaa;
              public string $bbb;
              public string $ccc;
          }
          
          class staticSet2 {
              public string $aaa;
              public string $bbb;
          }
          
          class staticSet3 {
              public bool $aaa;
              public bool $bbb;
              public bool $ccc;
          }
          
          $arraysOf=[];
          $t0 = microtime(true);
          $start=memory_get_usage(); 
          for ($i=0; $i<$noOfObjects; $i++) {
              $z = array(); // definition
              for ($j=0; $j<$noOfOperations; $j++) {
                  $z['aaa'] = 'aaa';
                  $z['bbb'] = 'bbb';
                  $z['ccc'] = $z['aaa'].$z['bbb'];
              }
              $arraysOf[]=$z;
          }
          $end=memory_get_usage();  
          echo 'arrays: '.(microtime(true) - $t0).PHP_EOL;
          echo 'memory: '.($end-$start).PHP_EOL;
          var_dump($z);
          unset($t0,$start,$end,$z,$arraysOf);
          echo '---------------------------------------'.PHP_EOL;
          $arraysOf=[];
          $t0 = microtime(true);
          $start=memory_get_usage(); 
          for ($i=0; $i<$noOfObjects; $i++) {
              $z = new set(); // definition
              for ($j=0; $j<$noOfOperations; $j++) {
                  $z->setKey('aaa','aaa');
                  $z->setKey('bbb','bbb');
                  $z->setKey('ccc',$z->readKey('aaa').$z->readKey('bbb'));
              }
              $arraysOf[]=$z;
          }
          $end=memory_get_usage();  
          echo 'dynamic obj: '.(microtime(true) - $t0).PHP_EOL;
          echo 'memory: '.($end-$start).PHP_EOL;
          var_dump($z);
          unset($t0,$start,$end,$z,$arraysOf);
          echo '---------------------------------------'.PHP_EOL;
          $arraysOf=[];
          $t0 = microtime(true);
          $start=memory_get_usage(); 
          for ($i=0; $i<$noOfObjects; $i++) {
              $z = new staticSet(); // definition
              for ($j=0; $j<$noOfOperations; $j++) {
                  $z->{'aaa'} = 'aaa';
                  $z->{'bbb'} = 'bbb';
                  $z->{'ccc'} = $z->{'aaa'}.$z->{'bbb'};
              }
              $arraysOf[]=$z;
          }
          $end=memory_get_usage();  
          echo 'static obj: '.(microtime(true) - $t0).PHP_EOL;
          echo 'memory: '.($end-$start).PHP_EOL;
          var_dump($z);
          unset($t0,$start,$end,$z,$arraysOf);
          echo '---------------------------------------'.PHP_EOL;
          $arraysOf=[];
          $t0 = microtime(true);
          $start=memory_get_usage(); 
          for ($i=0; $i<$noOfObjects; $i++) {
              $z = new staticSet2(); // definition
              for ($j=0; $j<$noOfOperations; $j++) {
                  $z->{'aaa'} = 'aaa';
                  $z->{'bbb'} = 'bbb';
                  $z->{'ddd'} = $z->{'aaa'}.$z->{'bbb'};
              }
              $arraysOf[]=$z;
          }
          $end=memory_get_usage();  
          echo 'static obj with an additional prop: '.(microtime(true) - $t0).PHP_EOL;
          echo 'memory: '.($end-$start).PHP_EOL;
          var_dump($z);
          unset($t0,$start,$end,$z,$arraysOf);
          echo '---------------------------------------'.PHP_EOL;
          $arraysOf=[];
          $t0 = microtime($noOfObjects);
          $start=memory_get_usage(); 
          for ($i=0; $i<$noOfObjects; $i++) {
              $z = new Ds\Map(); // definition
              for ($j=0; $j<$noOfOperations; $j++) {
                  $z->put('aaa','aaa');
                  $z->put('bbb','bbb');
                  $z->put('ccc',$z->get('aaa').$z->get('bbb'));
              }
              $arraysOf[]=$z;
          }
          $end=memory_get_usage();  
          echo 'Ds\Map: '.(microtime(true) - $t0).PHP_EOL;
          echo 'memory: '.($end-$start).PHP_EOL;
          var_dump($z);
          unset($t0,$start,$end,$z,$arraysOf);
          echo '---------------------------------------'.PHP_EOL;
          $arraysOf=[];
          $t0 = microtime(true);
          $start=memory_get_usage(); 
          for ($i=0; $i<$noOfObjects; $i++) {
              $z = new staticSet(); // definition
              for ($j=0; $j<$noOfOperations; $j++) {
                  $z->{'aaa'} = '1';
                  $z->{'bbb'} = '1';
                  $z->{'ccc'} = ($z->{'aaa'} && $z->{'bbb'});
              }
              $arraysOf[]=$z;
          }
          $end=memory_get_usage();  
          echo 'static obj with bool values: '.(microtime(true) - $t0).PHP_EOL;
          echo 'memory: '.($end-$start).PHP_EOL;
          var_dump($z);
          unset($t0,$start,$end,$z,$arraysOf);
          echo '---------------------------------------'.PHP_EOL;
          $arraysOf=[];
          $t0 = microtime(true);
          $start=memory_get_usage(); 
          for ($i=0; $i<$noOfObjects; $i++) {
              $z = new staticSet3(); // definition
              for ($j=0; $j<$noOfOperations; $j++) {
                  $z->{'aaa'} = '1';
                  $z->{'bbb'} = '1';
                  $z->{'ccc'} = ($z->{'aaa'} && $z->{'bbb'});
              }
              $arraysOf[]=$z;
          }
          $end=memory_get_usage();  
          echo 'static obj with defined bool values: '.(microtime(true) - $t0).PHP_EOL;
          echo 'memory: '.($end-$start).PHP_EOL;
          var_dump($z);
          unset($t0,$start,$end,$z,$arraysOf);
          echo '---------------------------------------'.PHP_EOL;
          $arraysOf=[];
          $t0 = microtime(true);
          $start=memory_get_usage(); 
          for ($i=0; $i<$noOfObjects; $i++) {
              $z = array('aaa' => '','bbb' => '','ccc' => ''); // definition
              for ($j=0; $j<$noOfOperations; $j++) {
                  $z['aaa'] = 'aaa';
                  $z['bbb'] = 'bbb';
                  $z['ccc'] = $z['aaa'].$z['bbb'];
              }
              $arraysOf[]=$z;
          }
          $end=memory_get_usage();  
          echo 'predefined array: '.(microtime(true) - $t0).PHP_EOL;
          echo 'memory: '.($end-$start).PHP_EOL;
          var_dump($z);
          unset($t0,$start,$end,$z,$arraysOf);
          echo '---------------------------------------'.PHP_EOL;
          
          
          echo 'phpversion '.phpversion().PHP_EOL;
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2011-06-10
            • 2019-10-01
            • 1970-01-01
            • 2010-11-14
            • 2015-08-29
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多