Должен ли я использовать ассоциативный массив или объект? - PullRequest
28 голосов
/ 14 декабря 2011

Как мы все знаем, json_decode дает вам возможность вернуть ассоциативный массив или объект.Есть много других ситуаций, когда у нас есть два варианта.Очевидно, что в некоторых случаях использование одного или другого является более «подходящим» в зависимости от типа данных, с которыми вы имеете дело (группа данных, относящихся к одному элементу, по сравнению со списком элементов).

Что ямне интересно, есть ли разница в эффективности использования одного против другого, с точки зрения памяти, скорости и т. д.?Меня особенно интересует время доступа для очень большого объекта - как это соотносится с очень большим массивом и почему?

Извините, если это уже обсуждалось, поиск ничего не дал.Я пишу тест, который может сказать мне, какой из них лучше, но не поможет понять, почему.

Ответы [ 3 ]

46 голосов
/ 14 декабря 2011

Многие программисты предпочитают использовать true в качестве второго аргумента json_decode , поскольку возвращенный ассоциативный массив будет очень похож на то, как вы обрабатываете объекты в javascript.

Возврат правильного объекта потребует чтения о том, как он используется, а что нет, и, поскольку большинство программистов хорошо знакомы с ассоциативными массивами, это более предпочтительно, особенно если код будет поддерживаться командой разработчиков. Код должен быть легко понятен.

Что касается вопросов о производительности, я не думаю, что вам нужно беспокоиться об этом, поскольку горлышко бутылки в большинстве (всех) случаев будет в другом месте. Если вы не анализируете массивную строку, и я имею в виду действительно огромную строку, вам не нужно делать какие-либо тесты. Я полагаю, что разница между возвратом массива сопоставления и надлежащего объекта будет незначительной.


Тест производительности (разбор)

Я нашел довольно большую строку json здесь и внес некоторые изменения, чтобы сделать ее еще больше, окончательный размер составляет 84 578 байт.

Затем я проанализировал строку, используя обе альтернативы (ассоциативный массив против объекта), по 1000 раз каждый, и я провел тест три раза. Результаты приведены ниже:

1-й пробег

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

2-й пробег

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

3-й пробег

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

Тест производительности (чтение / запись)

Этот тест показывает, какой из stdObject и Array() быстрее, я использую разобранный модифицированный файл 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;
}

1-й пробег

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

2-й пробег

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

3-й пробег

  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) (построено: 13 августа 2011 г. 19:04:57) Copyright (c) 1997-2011

PHP Group Zend Engine v2.3.0, Copyright (c) 1998-2011 Zend

Технологии

4 голосов
/ 22 декабря 2011

Тест производительности (время доступа)

Вот мой тест.Меня больше всего интересовало время доступа.Я заполнил массив 10000 переменных, отлил его как объект, затем для объекта и массива я просто получил доступ к одной из переменных 10000 раз.Часть кода:

$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% в приведенном выше наборе).Индекс переменной, к которой мы пытаемся получить доступ, не влияет на время доступа.

Видя комментарии выше, мне стыдно сказать, что я нахожусь на PHP 5.3.4.

1 голос
/ 14 декабря 2011

Не совсем уверенно, но вы могли бы написать что-то простое, а затем использовать FireFox Firebug, чтобы увидеть, что было сообщение в мс.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...