【问题标题】:Should I use an associative array or an object?我应该使用关联数组还是对象?
【发布时间】:2012-01-19 20:26:29
【问题描述】:

众所周知,json_decode 提供了返回关联数组或对象的选项。在许多其他情况下,我们也有这两种选择。显然,在某些情况下,根据您正在处理的数据类型(与一个项目有关的一组数据与一个项目列表),使用一个或另一个更“合适”。

我想知道的是,在内存、速度等方面,使用一个与另一个的效率有什么不同吗?我对一个非常大的对象的访问时间特别感兴趣 - 与一个非常大的数组相比如何,为什么?

抱歉,如果之前已经讨论过这个问题,搜索结果一无所获。我正在编写一个基准,它可能会告诉我哪个更好,但不会帮助我理解原因。

【问题讨论】:

  • 我不知道 PHP 的复杂性,但我想它们会很相似,因为需要管理 PHP 数组(它们是动态的)。跨度>
  • 您可以使用 xdebug 分析器查看它不会在 *cachegrind 图中产生明显的差异。记忆方面也没有。普通数组的优点是在缺少属性的情况下不会导致致命错误。

标签: php arrays performance object


【解决方案1】:

我不完全确定,但你可以写一些简单的东西,然后使用 FireFox 的萤火虫来查看帖子的往返行程是多少毫秒。

【讨论】:

  • 我正在编写一个基准测试,它可能会告诉我哪个更有效,但不会真正帮助我理解原因。
  • 啊,抱歉,我不确定为什么。如果我不得不猜测,我会说数组在内存中更便宜,因为与带有额外结构的对象相比,它的开销更少。对于数据的访问时间,大多数对象都带有用于选择、查找、排序等的最佳实践方法,因此该对象很可能是最适合访问时间的对象。
  • @andrewtweber 你的基准测试结果如何?我在帖子中提供了一个。
【解决方案2】:

许多程序员更喜欢使用true 作为json_decode 的第二个参数,因为返回的assoc 数组 将与您在javascript 中处理对象的方式非常相似。

返回一个正确的对象需要阅读有关如何使用和不使用此类的信息,并且由于大多数程序员都非常熟悉关联数组,因此更可取,尤其是如果代码将由一组开发人员维护。代码应该易于理解。

关于性能问题,我认为您无需担心,因为大多数(所有)情况下的瓶颈都在其他地方。除非你正在解析一个巨大的字符串,我的意思是真的很大,否则你不需要做任何基准测试。我相信返回一个 assoc 数组和一个正确的对象之间的区别会很小。


性能基准(解析)

我找到了一个相当大的 json 字符串 here 并进行了一些调整以使其更大,最终大小为 84 578 字节。

然后,我使用两种替代方法(关联数组与对象)分别解析字符串 1000 次,并运行了 3 次测试。结果如下:

第一次运行

  JSON object exec: 4.06122 s
  JSON assoc  exec: 3.28679 s
-------------------------------------
assoc is faster by 19.07%

第二次运行

  JSON object exec: 4.09614 s
  JSON assoc  exec: 3.29216 s
-------------------------------------
assoc is faster by 19.63%

第三次运行

  JSON object exec: 4.08762 s
  JSON assoc  exec: 3.29960 s
-------------------------------------
assoc is faster by 19.28%

性能基准(读/写)

这个基准是为了显示stdObjectArray() 中的哪一个更快,我使用的是一个解析后的修改过的 json 文件(比之前的基准更大)。

每个读/写测试都运行了 100 000 次(即下面给出的代码被执行了很多次)。

json_decode ($json_data)

for ($i =0; $i < 24; ++$i){
  $a = $object[$i]->user->profile_sidebar_border_color . "stackoverflow";
  $object[$i]->nested->entities->user_mentions[0]->indices[$i&1] += 1;
}

json_decode ($json_data, true)

for ($i =0; $i < 24; ++$i){
  $a = $assoc[$i]['user']['profile_sidebar_border_color'] . "stackoverflow";
  $assoc[$i]['nested']['entities']['user_mentions'][0]['indices'][$i&1] += 1;
}

第一次运行

  JSON object read/write: 3.05421 s
  JSON assoc  read/write: 2.51932 s
-------------------------------------
assoc is faster by 17.51%

第二次运行

  JSON object read/write: 3.06307 s
  JSON assoc  read/write: 2.52701 s
-------------------------------------
assoc is faster by 17.50%

第三次运行

  JSON object read/write: 3.06109 s
  JSON assoc  read/write: 2.52248 s
-------------------------------------
assoc is faster by 17.60%

PHP 版本

PHP 5.3.6 (cli)(构建时间:2011 年 8 月 13 日 19:04:57)版权所有 (c) 1997-2011

PHP Group Zend Engine v2.3.0,版权所有 (c) 1998-2011 Zend

技术

【讨论】:

  • @DigitalPrecision 好多年没写过生产PHP了,所以升级比较慢,不过还是谢谢提醒!
  • @refp 谢谢!很好的答案。我提交了我的基准作为另一个答案;尽管访问时间没有像读/写那样受到影响,但得出了类似的结果。
  • @andrewtweber 你没有尝试嵌套读/写,这是另一个有趣的部分,至少对我来说:)
  • 请记住,虽然关联数组是一种更简单的约定,但它也可能导致由简单的拼写错误引起的更难以调试的问题(请参阅this answer)。
  • 内存呢?什么消耗最多?
【解决方案3】:

性能基准(访问时间)

这是我的基准。我最感兴趣的是访问时间。我用 10,000 个变量填充了一个数组,将其转换为一个对象,然后对于对象和数组,我只需访问其中一个变量 10,000 次。部分代码:

$arr = array();
for( $i=0; $i<10000; $i++ ) {
    $arr['test'.$i] = 'Hello. My name is Inigo Montoya. You killed my father. Prepare to die.';
}
$obj = (object)$arr;

$tests = array(0,1000,2000,3000,4000,5000,6000,7000,8000,9999);

foreach( $tests as $test ) {
    $test_name = 'test'.$test;

    $start = microtime(true);
    for( $i=0; $i<10000; $i++ ) {
        $var = $obj->$test_name;
    }
    $end = microtime(true);
    $elapsed = $end - $start;

    $start = microtime(true);
    for( $i=0; $i<10000; $i++ ) {
        $var = $arr[$test_name];
    }
    $end = microtime(true);
    $elapsed = $end - $start;
}

结果

我多次运行测试;这是典型的结果集之一;时间以毫秒为单位。

            Object    Array
------------------------------
test0       4.4880    4.1411
test1000    4.5588    4.2078
test2000    4.5812    4.2109
test3000    4.5240    4.2000
test4000    4.5800    4.2648
test5000    4.5929    4.2000
test6000    4.5311    4.2260
test7000    4.6101    4.2901
test8000    4.5331    4.1370
test9999    4.5100    4.1430

阵列平均比对象快 8.3%(在上面的集合中为 7.7%)。我们试图访问的变量的索引对访问时间没有影响。

看到上面的 cmets,我不好意思说我使用的是 PHP 5.3.4。

【讨论】:

  • 内存呢?什么消耗最多?
猜你喜欢
  • 2016-04-10
  • 1970-01-01
  • 2013-06-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-09
  • 2016-08-03
相关资源
最近更新 更多