28

As we all know, json_decode gives you the option of returning an associative array or an object. There are many other situations where we have the two options as well. Obviously in some cases using one or the other is more "appropriate" based on the type of data you're dealing with (a group of data pertaining to one item vs. a list of items).

What I'm wondering is, is there any difference in efficiency in using one vs. the other, in terms of memory, speed, etc? I'm particularly interested in access time for a very large object - how does that compare to a very large array, and why?

Sorry if this has been discussed before, search turned up nothing. I'm writing a benchmark, which may tell me which one is better, but won't help me understand why.

andrewtweber
  • 24,520
  • 22
  • 88
  • 110
  • I don't know about the intricacies of PHP, but I'd imagine they'd be similar due to a PHP array needing to be managed (they're dynamic, for one). – Bojangles Dec 14 '11 at 00:22
  • You can use the xdebug profiler to see that it won't make a noticeable difference in the *cachegrind graph. Memory-wise neither. Normal arrays have the advantage of not causing fatal errors in case of absent attributes. – mario Dec 14 '11 at 00:25

3 Answers3

48

Many programmers prefer using true as the second argument to json_decode since the returned assoc array will be very similar to how you handle objects in javascript.

Returning a proper object will require reading about how such is used and what not, and since most programmers are well familiar with associative arrays that's more preferrable, especially if the code will be maintained by a team of developers. Code should be easily understandable.

Regarding questions about performance I don't think you'll need to worry about that since the bottle neck in most (all) cases will be elsewhere. Unless you are parsing a massive string, and by that I mean really huge, you shouldn't need to make any benchmarks. I believe the difference between returning an assoc array vs a proper object will be minor.


Performance Benchmark (parsing)

I found a rather large json string here and made some adjustments to make it even bigger, final size is 84 578 bytes.

I then parsed the string using both alternatives (associative array vs object) 1 000 times each, and I ran the test three times. The results are given below:

1st run

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

2nd run

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

3rd run

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

Performance Benchmark (read/write)

This benchmark is to show which one of stdObject and Array() is faster, I'm using a parsed modified json file (bigger one) than in the previous benchmark.

Each read/write test was run 100 000 times (ie. the code given below was executed that many times).

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;
}

1st run

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

2nd run

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

3rd run

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

PHP version

PHP 5.3.6 (cli) (built: Aug 13 2011 19:04:57) Copyright (c) 1997-2011

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

Technologies

Community
  • 1
  • 1
Filip Roséen - refp
  • 62,493
  • 20
  • 150
  • 196
  • @DigitalPrecision I haven't written production PHP in many years, therefore upgrades are slacking behind, thanks for the reminder though! – Filip Roséen - refp Dec 14 '11 at 01:16
  • @refp Thanks! Great answer. I submitted my benchmark as another answer; came up with similar results although access time wasn't impacted as much as read/write. – andrewtweber Dec 21 '11 at 21:20
  • @andrewtweber You didn't try out nested read/writes though, which is another interesting part, at least to me :) – Filip Roséen - refp Dec 21 '11 at 21:21
  • Keep in mind that although associative arrays are an easier convention, it could also lead to more hard-to-debug issues caused by simple typos (see [this answer](http://stackoverflow.com/questions/2056931/value-objects-vs-associative-arrays-in-php)). – thdoan Apr 13 '16 at 07:24
  • what about memory? what consumes the most? – Luca C. Apr 25 '20 at 13:14
4

Performance Benchmark (access time)

Here is my benchmark. I was mostly interested in access time. I populated an array with 10,000 variables, cast it as an object, then for both the object and array I simply accessed one of the variables 10,000 times. Part of the code:

$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;
}

Results

I ran the test multiple times; here is one of the typical result sets; times are in milliseconds.

            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

The array was an average of 8.3% faster than the object (7.7% in the set above). The index of the variable we are trying to access has no effect on the access time.

Seeing the comments above I'm embarrassed to say I'm on PHP 5.3.4.

andrewtweber
  • 24,520
  • 22
  • 88
  • 110
1

Not entirely sure off the top of my head, but you could write something simple and then use FireFox's firebug to see what the round trip of the post was in ms.

Travis J
  • 81,153
  • 41
  • 202
  • 273
  • I'm writing a benchmark, which may tell me which one is more efficient, but won't really help me understand why. – andrewtweber Dec 14 '11 at 00:26
  • Ah, sorry, I am not certain of the why. If I had to guess, I would say the array was cheaper in memory because there is less overhead versus an object which comes with extra structure. For access time to data, most objects come with best practice methods for selecting, finding, sorting, etc. so the object is most likely best for access time. – Travis J Dec 14 '11 at 00:33
  • @andrewtweber What was your result using your benchmark? I've provided one in my post. – Filip Roséen - refp Dec 14 '11 at 01:05