Search code examples
phparraysmemory-managementcopy-on-write

Does PHP copy an array subset when assigning it to a variable?


Consider a large array $stats with many keys, one of them being "visitors" with a large array as value.

What does PHP do when writing $visitors = $stats['visitors'] - does it copy the array structure and values or does it only use a reference to the original array?

Should I be using $visitors = &$stats['visitors'] instead?

Data is only being read from.

I know PHP uses copy on write when passing arrays to methods or when assigning variables to variables, but does CoW also work in my scenario with an array subset?


Solution

  • Consider a large array $stats with many keys, one of them being "visitors" with a large array as value.

    The description hints at the answer to your question. You've correctly noticed that values in PHP arrays are just independent values - you don't have to do anything special to make an array multidimensional, you just put an array as a value inside another array.

    The answer to this...

    What does PHP do when writing $visitors = $stats['visitors']?

    ... is therefore exactly the same as the answer to this:

    What does PHP do when writing $visitors = $some_visitors?

    The only thing that matters is the value on the right-hand side. In your case, the value you're assigning is a large array; you just happen to know where to find that large array value as an item in another array.

    does it copy the array structure and values or does it only use a reference to the original array?

    As you correctly say, PHP uses copy-on-write for arrays: the variable will be pointed to the same memory already containing the large array, and its reference count will be incremented. Only if one of the "copies" needs to be modified will a new copy actually be made in memory.

    Should I be using $visitors = &$stats['visitors'] instead?

    Almost certainly not. In fact, doing so might make it worse, because references break some of the assumptions the optimising code relies on. Before PHP 7, doing so would immediately require a separate copy of anything previously using copy-on-write; that's not the case any more (read this blog post for lots of technical details on what changed) but you're still unlikely to make anything better with references, unless you are actually writing to the array.