title: Duplicate array without doubling peak memory usage in PHP
body: <p>I'm looking for the most memory efficient way to process each element in a large PHP array that is already in memory and convert it to another format with minimal peak memory usage increase and without writing data out to disk.</p>
  <p>My initial thought was as I loop through the $source_array, I could simply unset() each row to free up memory. However that actually increases the peak memory usage.</p>
  <p>Below is example code to showcase the situation:</p>
  <pre><code>$source_array = array_fill( 0, 500000, [ 'col1' =&gt; 'val1', 'col2' =&gt; 'val2', 'col3' =&gt; 'val3', 'col4' =&gt; 'val4', 'col5' =&gt; 'val5',] );
  echo &quot;Initial Memory Usage: &quot;. memory_get_usage()  .' Peak Memory Usage: '. memory_get_peak_usage() .&quot;&lt;br&gt;\n&quot;;
  
  $destination_array = [];
  foreach( $source_array as $key =&gt; $row ) {
      $destination_array[$key] = $row; //Assume some manipulation of $row here.
  
      //$source_array[$key] = null; //Causes peak memory to increase.
      //unset( $source_array[$key] ); //Causes peak memory to increase
      if ( $key &gt; 0 &amp;&amp; $key % 100000 == 0 ) {
          echo &quot;  $key. Inside Loop Memory Usage: &quot;. memory_get_usage()  .' Inside Loop Peak Memory Usage: '. memory_get_peak_usage() .&quot;&lt;br&gt;\n&quot;; //Peak memory usage is double initial memory usage.
          gc_collect_cycles();
      }
  }
  unset( $source_array );
  echo &quot;Final Memory Usage: &quot;. memory_get_usage()  .' Final Peak Memory Usage: '. memory_get_peak_usage() .&quot;&lt;br&gt;\n&quot;; //Peak memory usage is double initial memory usage.
  </code></pre>
  <blockquote>
  <p>Output: <strong>NOTICE</strong> Initial and Final memory usage are identical, but peak memory is double.</p>
  <p>Initial Memory Usage: 17250856 Peak Memory Usage: 17250952<br>
  100000. Inside Loop Memory Usage: 21449400 Inside Loop Peak Memory Usage: 21449520<br>
  200000. Inside Loop Memory Usage: 25643704 Inside Loop Peak Memory Usage: 25643824<br>
  300000. Inside Loop Memory Usage: 34032312 Inside Loop Peak Memory Usage: 34032432<br>
  400000. Inside Loop Memory Usage: 34032312 Inside Loop Peak Memory Usage: 34032512<br> Final Memory Usage: 17250856 Final Peak Memory
  Usage: 34032512</p>
  </blockquote>
  <p>The best I have been able to come up with so far is using SplFixedArray in the following way:</p>
  <pre><code>$source_array = array_fill( 0, 500000, [ 'col1' =&gt; 'val1', 'col2' =&gt; 'val2', 'col3' =&gt; 'val3', 'col4' =&gt; 'val4', 'col5' =&gt; 'val5',] );
  echo &quot;Initial Memory Usage: &quot;. memory_get_usage()  .' Peak Memory Usage: '. memory_get_peak_usage() .&quot;&lt;br&gt;\n&quot;;
  
  $source_array = SplFixedArray::fromArray( $source_array );
  echo &quot;Pre-Loop Memory Usage: &quot;. memory_get_usage()  .' Pre-Loop Peak Memory Usage: '. memory_get_peak_usage() .&quot;&lt;br&gt;\n&quot;;
  
  $destination_array = new SplFixedArray( count( $source_array ) ); //This reduces peak memory by about 20-30%.
  foreach( $source_array as $key =&gt; $row ) {
      $destination_array[$key] = $row; //Assume some manipulation of $row here.
  
      //$source_array[$key] = null; //Causes peak memory to increase.
      //unset( $source_array[$key] ); //Causes peak memory to increase
      if ( $key &gt; 0 &amp;&amp; $key % 100000 == 0 ) {
          echo &quot;  $key. Inside Loop Memory Usage: &quot;. memory_get_usage()  .' Inside Loop Peak Memory Usage: '. memory_get_peak_usage() .&quot;&lt;br&gt;\n&quot;; //Peak memory usage is double initial memory usage.
          gc_collect_cycles();
      }
  }
  unset( $source_array );
  echo &quot;Final Memory Usage: &quot;. memory_get_usage()  .' Final Peak Memory Usage: '. memory_get_peak_usage() .&quot;&lt;br&gt;\n&quot;; //Peak memory usage is double initial memory usage.
  </code></pre>
  <blockquote>
  <p>Output:</p>
  <p>Initial Memory Usage: 17250920 Peak Memory Usage: 17251016<br>
  Pre-Loop Memory Usage: 8473216 Pre-Loop Peak Memory Usage:
  25254608<br>
  100000. Inside Loop Memory Usage: 16477064 Inside Loop Peak Memory Usage: 25254608<br>
  200000. Inside Loop Memory Usage: 16477120 Inside Loop Peak Memory Usage: 25254608<br>
  300000. Inside Loop Memory Usage: 16477120 Inside Loop Peak Memory Usage: 25254608<br>
  400000. Inside Loop Memory Usage: 16477120 Inside Loop Peak Memory Usage: 25254608<br> Final Memory Usage: 8473272 Final Peak Memory
  Usage: 25254608</p>
  </blockquote>
  <p>While a ~30% improvement over the original is decent, I feel as though I should be able to do this with a near zero peak memory increase. Any ideas?</p>