NotionCommotion Posted January 10, 2020 Share Posted January 10, 2020 When will modern PHP copy an array by reference only instead of reassigning to memory? For instance, when I execute $bigArray=$stmt->execute([$id]), PHP utilizes memory to store the data. But then when I execute $dataHolders[] = new DataHolder($bigArray), I believe $bigArray is passed by reference and a new copy of $bigArray will not be stored in memory. If in DataHolder::__construct, I executed $data[]='bla', then it is my understanding that PHP would see that the array is being modified and will automatically make a copy, but I am not doing so and just state this to confirm my understanding. The part that I am uncertain about is not the first time data is retrieved but any additional times. When I execute the next $bigArray=$stmt->execute([$id]), will PHP need to first store in memory the array that DataHolder::data references, then release the memory associated with $bigArray, and then store in memory the new $bigArray? <?php class DataHolder { private $data; public function __construct(array $data) { $this->data=$data; //$this->data[]='bla'; <-- I believe this will force PHP to make a new copy of the array but I am not doing so } } $dataHolders=[]; foreach($ids as $id) { $bigArray=$stmt->execute([$id]); $dataHolders[] = new DataHolder($bigArray); } Quote Link to comment https://forums.phpfreaks.com/topic/309819-how-does-php-determine-to-create-a-new-copy-of-a-copied-array/ Share on other sites More sharing options...
requinix Posted January 10, 2020 Share Posted January 10, 2020 Don't think about it in terms of references. Those are really just about &s. What PHP does with everything, not just arrays, is called copy-on-write. Meaning PHP will reuse a value up until you try to change it. That is when it starts making a copy. That's why they say never to use references to save memory: PHP is already saving memory for you. 1 Quote Link to comment https://forums.phpfreaks.com/topic/309819-how-does-php-determine-to-create-a-new-copy-of-a-copied-array/#findComment-1573309 Share on other sites More sharing options...
gizmola Posted January 10, 2020 Share Posted January 10, 2020 In simplest form, PHP implements symbol table(s) which store variable names used in the script and zval(s) which are the actual data structures that manage variables. You could have 3 variable names: $a = $b = $c = 5; And this will have 3 symbol table entries but only 1 zval will be created. The zval has a reference count, so not surprisingly, this zval will have the value 3, indicating that there are 3 symbols using this zval. Now you change the value of one of the variables: $a++; As requinix states, PHP will make a new zval and copy the original value from the first zval. The symbol table entry for $a gets changed to point to the new zval, and the original zval has its reference count decremented by 1. $b and $c still point to the original zval. If you want to really geek out on PHP internals, there's an excellent series on PHP 7 vs 5 changes. The author also wrote a great article on the hashtable implementation that powers a lot of things in PHP including arrays. https://nikic.github.io/2015/05/05/Internal-value-representation-in-PHP-7-part-1.html https://nikic.github.io/2015/06/19/Internal-value-representation-in-PHP-7-part-2.html https://nikic.github.io/2014/12/22/PHPs-new-hashtable-implementation.html Quote Link to comment https://forums.phpfreaks.com/topic/309819-how-does-php-determine-to-create-a-new-copy-of-a-copied-array/#findComment-1573312 Share on other sites More sharing options...
NotionCommotion Posted January 11, 2020 Author Share Posted January 11, 2020 I know I am not known for specific question, but do have one this time. 20 hours ago, NotionCommotion said: When I execute the next $bigArray=$stmt->execute([$id]), will PHP need to first store in memory the array that DataHolder::data references, then release the memory associated with $bigArray, and then store in memory the new $bigArray? 16 hours ago, gizmola said: As requinix states, PHP will make a new zval and copy the original value from the first zval. The symbol table entry for $a gets changed to point to the new zval, and the original zval has its reference count decremented by 1. $b and $c still point to the original zval. gizmola's response makes me feel that the above will cause PHP to copy the original value. True? Guess I can prevent doing so with the following... $dataHolders[] = new DataHolder($stmt->execute([$id])); //or $bigArray[]=$stmt->execute([$id]); $dataHolders[] = new DataHolder(reset($bigArray)); Quote Link to comment https://forums.phpfreaks.com/topic/309819-how-does-php-determine-to-create-a-new-copy-of-a-copied-array/#findComment-1573333 Share on other sites More sharing options...
benanamen Posted January 11, 2020 Share Posted January 11, 2020 Hi @NotionCommotion, long time no chat. This is all interesting stuff. I was just wondering, are you actually having a problem to where this matters or is this just for learning? Quote Link to comment https://forums.phpfreaks.com/topic/309819-how-does-php-determine-to-create-a-new-copy-of-a-copied-array/#findComment-1573348 Share on other sites More sharing options...
kicken Posted January 11, 2020 Share Posted January 11, 2020 5 hours ago, NotionCommotion said: gizmola's response makes me feel that the above will cause PHP to copy the original value. True? Guess I can prevent doing so with the following... If you're talking about the code in your OP causing a copy to be made, then it wouldn't as posted. If you un-comment that line that appends to the array then that would cause a copy to be created. A copy is only generated when your code does something that would cause the array to be different from it's original. Simply passing it around between functions/objects doesn't do this. Side note: $stmt->execute(); doesn't return an array (assuming $stmt instanceof PDOStatement). You'd want $stmt->fetchAll(); to get an array; Quote Link to comment https://forums.phpfreaks.com/topic/309819-how-does-php-determine-to-create-a-new-copy-of-a-copied-array/#findComment-1573357 Share on other sites More sharing options...
NotionCommotion Posted January 12, 2020 Author Share Posted January 12, 2020 16 hours ago, kicken said: A copy is only generated when your code does something that would cause the array to be different from it's original. Simply passing it around between functions/objects doesn't do this. Side note: $stmt->execute(); doesn't return an array (assuming $stmt instanceof PDOStatement). You'd want $stmt->fetchAll(); to get an array; I understand older versions of PHP would actually make a copy, but that this is no longer the case and it is only copied when it is changed. When I fetch the first set of results, I obviously need to save the content in memory (just realized my typo and forgot the fetchAll). But then when I fetch the second and future data sets, I am reassigning the $bigArray variable to this new data set which "maybe" is effectively changing it. You know, it would be quicker to actually test this. Quote Link to comment https://forums.phpfreaks.com/topic/309819-how-does-php-determine-to-create-a-new-copy-of-a-copied-array/#findComment-1573384 Share on other sites More sharing options...
NotionCommotion Posted January 12, 2020 Author Share Posted January 12, 2020 I ended up mocking it up and didn't expect the following results. Creating the initial array uses 11MB, copying it uses very little, and changing it uses 529KB. I would have expected changing it would have used the same as creating it. And then when I reassign $bigArray with new values, it uses 11MB which I wasn't sure whether to expect or not and this was the basis of my original question. But then I don't reassign $bigArray but pass the array directly to the class, and it also uses 11MB which I definitely did not expect and thought that it would be saved only as a reference and use very little memory. I am using PHP7.4.1. What is going on? Thanks <?php error_reporting(E_ALL); ini_set('display_errors', 1); $settings=parse_ini_file(__DIR__.'/../../config.ini',true); $db=$settings['mysql']; $pdo=new \PDO("mysql:host={$db['host']};dbname={$db['dbname']};charset={$db['charset']}",$db['username'],$db['password'],array(\PDO::ATTR_EMULATE_PREPARES=>false,\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY=>true,\PDO::ATTR_ERRMODE=>\PDO::ERRMODE_EXCEPTION,\PDO::ATTR_DEFAULT_FETCH_MODE=>\PDO::FETCH_ASSOC)); $stmt=$pdo->query('SELECT * FROM test'); function display($memory) { $s=''; foreach($memory as $i => $m) { $delta=$i>0 ?[$m[1]-$memory[$i-1][1], $m[2]-$memory[$i-1][2], $m[3]-$memory[$i-1][3], $m[4]-$memory[$i-1][4]] :[null, null, null, null]; $m=array_merge($m, $delta); $s.='<tr><td>'.implode('</td><td>', $m).'</td></tr>'; } echo "<table><tbody><tr><td>Test</td><td>Used</td><td>Peak</td><td>Peak Used</td><td>Peak Allocated</td><td>Used Change</td><td>Peak Change</td><td>Peak Used Change</td><td>Peak Allocated Change</td></tr>$s</tbody></table>"; } function logger($msg, $log=true) { global $memory; $m = [$msg, round(memory_get_usage()/1000),round( memory_get_peak_usage()/1000), round(memory_get_usage(true)/1000), round(memory_get_peak_usage(true)/1000)]; if($log) $memory[] = $m; return $m; } function addDelta($msg, $before, $after) { global $memory; $m = [$msg, $after[1]-$before[1], $after[2]-$before[2], $after[3]-$before[3], $after[4]-$before[4]]; $memory[]=$m; return $m; } function getData($stmt) { $data=[]; for ($i = 0; $i <= 3; $i++) { $stmt->execute(); $data = array_merge($data, $stmt->fetchAll()); } return $data; } class DataHolder { private $data; public function __construct(array $data) { $this->data=$data; //$this->data[]='bla'; <-- I believe this will force PHP to make a new copy of the array but I am not doing so } } $memory=[]; logger('initial'); $bigArray1=getData($stmt); logger('after creating first data set'); $bidArrayCopy=$bigArray1; logger('after copying first data set'); $bigArray1[]=123; logger('after modifying first data set'); $dataHolders=[]; $log1=logger(null, false); for ($i = 1; $i <= 5; $i++) { logger("Copy Loop $i - Before"); $stmt->execute(); $bigArray=getData($stmt); $dataHolders[] = new DataHolder($bigArray); logger("Copy Loop $i - After"); } $log2=logger(null, false); $deltaCopy = addDelta('delta copy', $log1, $log2); for ($i = 1; $i <= 5; $i++) { logger("Set Loop $i - Before"); $stmt->execute(); $dataHolders[] = new DataHolder(getData($stmt)); logger("Set Loop $i - After"); } $log3=logger(null, false); $deltaSet = addDelta('delta set', $log2, $log3); addDelta('delta copy set', $deltaCopy, $deltaSet); display($memory); | Test | Used | Peak | Peak Used | Peak Allocated | Used Change | Peak Change | Peak Used Change | Peak Allocated Change | |--------------------------------|--------|--------|-----------|----------------|-------------|-------------|------------------|-----------------------| | initial | 1345 | 1345 | 2097 | 2097 | | | | | | after creating first data set | 12631 | 13294 | 2097 | 2097 | 11286 | 11949 | 0 | 0 | | after copying first data set | 12631 | 13294 | 2097 | 2097 | 0 | 0 | 0 | 0 | | after modifying first data set | 13160 | 13294 | 2097 | 2097 | 529 | 0 | 0 | 0 | | Copy Loop 1 - Before | 13161 | 13294 | 2097 | 2097 | 1 | 0 | 0 | 0 | | Copy Loop 1 - After | 24447 | 25110 | 2097 | 2097 | 11286 | 11816 | 0 | 0 | | Copy Loop 2 - Before | 24447 | 25110 | 2097 | 2097 | 0 | 0 | 0 | 0 | | Copy Loop 2 - After | 35733 | 36396 | 2097 | 2097 | 11286 | 11286 | 0 | 0 | | Copy Loop 3 - Before | 35734 | 36396 | 2097 | 2097 | 1 | 0 | 0 | 0 | | Copy Loop 3 - After | 47020 | 47683 | 2097 | 2097 | 11286 | 11287 | 0 | 0 | | Copy Loop 4 - Before | 47020 | 47683 | 2097 | 2097 | 0 | 0 | 0 | 0 | | Copy Loop 4 - After | 58306 | 58969 | 2097 | 2097 | 11286 | 11286 | 0 | 0 | | Copy Loop 5 - Before | 58307 | 58969 | 2097 | 2097 | 1 | 0 | 0 | 0 | | Copy Loop 5 - After | 69592 | 70256 | 4194 | 4194 | 11285 | 11287 | 2097 | 2097 | | delta copy | 56433 | 56962 | 2097 | 2097 | -13159 | -13294 | -2097 | -2097 | | Set Loop 1 - Before | 69594 | 70256 | 4194 | 4194 | 13161 | 13294 | 2097 | 2097 | | Set Loop 1 - After | 80879 | 81543 | 16777 | 16777 | 11285 | 11287 | 12583 | 12583 | | Set Loop 2 - Before | 80881 | 81543 | 16777 | 16777 | 2 | 0 | 0 | 0 | | Set Loop 2 - After | 92166 | 92830 | 27263 | 27263 | 11285 | 11287 | 10486 | 10486 | | Set Loop 3 - Before | 92167 | 92830 | 27263 | 27263 | 1 | 0 | 0 | 0 | | Set Loop 3 - After | 103453 | 104116 | 39846 | 39846 | 11286 | 11286 | 12583 | 12583 | | Set Loop 4 - Before | 103453 | 104116 | 39846 | 39846 | 0 | 0 | 0 | 0 | | Set Loop 4 - After | 114739 | 115402 | 50332 | 50332 | 11286 | 11286 | 10486 | 10486 | | Set Loop 5 - Before | 114740 | 115402 | 50332 | 50332 | 1 | 0 | 0 | 0 | | Set Loop 5 - After | 126026 | 126689 | 60817 | 60817 | 11286 | 11287 | 10485 | 10485 | | delta set | 56433 | 56433 | 56623 | 56623 | -69593 | -70256 | -4194 | -4194 | | delta copy set | 0 | -529 | 54526 | 54526 | -56433 | -56962 | -2097 | -2097 | Quote Link to comment https://forums.phpfreaks.com/topic/309819-how-does-php-determine-to-create-a-new-copy-of-a-copied-array/#findComment-1573389 Share on other sites More sharing options...
requinix Posted January 12, 2020 Share Posted January 12, 2020 8 hours ago, NotionCommotion said: Creating the initial array uses 11MB, copying it uses very little, and changing it uses 529KB. I would have expected changing it would have used the same as creating it. You only changed a 529KB/11MB portion of it. PHP doesn't need to create a whole new damn array if you change something in the middle of it... 8 hours ago, NotionCommotion said: And then when I reassign $bigArray with new values, it uses 11MB which I wasn't sure whether to expect or not and this was the basis of my original question. I can't tell if you're saying it added 11MB or did not drop 11MB. 8 hours ago, NotionCommotion said: But then I don't reassign $bigArray but pass the array directly to the class, and it also uses 11MB which I definitely did not expect and thought that it would be saved only as a reference and use very little memory. Ditto. Also, stop calling it a reference. It is not a reference. Quote Link to comment https://forums.phpfreaks.com/topic/309819-how-does-php-determine-to-create-a-new-copy-of-a-copied-array/#findComment-1573414 Share on other sites More sharing options...
kicken Posted January 13, 2020 Share Posted January 13, 2020 I re-wrote your test script in a way that provides data that is easier to interpret (IMO) and doesn't require a database: <?php function display($memory){ $s = ''; $prev = array_fill(0, 5, 0); $headers = ['Message', 'Usage', 'Peak', 'Usage (Real)', 'Peak (Real)', 'Usage Delta', 'Peak Delta', 'Usage Delta (Real)', 'Peak Delta (Real)']; foreach ($memory as $m){ $data = [ $m[0] , fmt($m[1]) , fmt($m[2]) , fmt($m[3]) , fmt($m[4]) , fmt($m[1] - $prev[1]) //Usage delta , fmt($m[2] - $prev[2]) //Peak delta , fmt($m[3] - $prev[3]) // Usage delta (real) , fmt($m[4] - $prev[4]) // Peak delta (real) ]; $s .= '<tr><td>' . implode('</td><td>', $data) . '</td></tr>'; $prev = $m; } echo '<table><thead><tr><th>' . implode('</th><th>', $headers) . '</th></tr></thead>'; echo '<tbody>' . $s . '</tbody></table>'; } function logger($msg){ global $memory; $usage = round(memory_get_usage()); $peak = round(memory_get_peak_usage()); $usageReal = round(memory_get_usage(true)); $peakReal = round(memory_get_peak_usage(true)); $m = [$msg, $usage, $peak, $usageReal, $peakReal]; $memory[] = $m; } function fmt($size){ static $suffix = ['B', 'KB', 'MB', 'GB']; $idx = 0; $negative = $size < 0; $size = abs($size); while ($size > 1024 && $idx < 3){ $size /= 1024; $idx++; } return sprintf('%0.2f %s', $size * ($negative ? -1 : 1), $suffix[$idx]); } function getData(){ $data = []; for ($i = 0; $i < 11; $i++){ $data[] = file_get_contents('1kb.txt'); } return $data; } class DataHolder { private $data; public function __construct(array $data){ $this->data = $data; //$this->data[]='bla'; <-- I believe this will force PHP to make a new copy of the array but I am not doing so } } $memory = []; logger('initial'); $bigArray1 = getData(); logger('after creating first data set'); $bidArrayCopy = $bigArray1; logger('after copying first data set'); $bigArray1[] = 'hello'; logger('after modifying first data set'); $dataHolders = []; for ($i = 1; $i <= 5; $i++){ logger("Copy Loop $i - Before"); $bigArray = getData(); $dataHolders[] = new DataHolder($bigArray); logger("Copy Loop $i - After"); } for ($i = 1; $i <= 5; $i++){ logger("Set Loop $i - Before"); $dataHolders[] = new DataHolder(getData()); logger("Set Loop $i - After"); } display($memory); Here's the results using values similar to the 11MB size you got. +--------------------------------+-----------+-----------+--------------+-------------+-------------+------------+--------------------+-------------------+ | Message | Usage | Peak | Usage (Real) | Peak (Real) | Usage Delta | Peak Delta | Usage Delta (Real) | Peak Delta (Real) | +--------------------------------+-----------+-----------+--------------+-------------+-------------+------------+--------------------+-------------------+ | initial | 419.97 KB | 456.24 KB | 2.00 MB | 2.00 MB | 419.97 KB | 456.24 KB | 2.00 MB | 2.00 MB | | after creating first data set | 11.45 MB | 11.47 MB | 22.00 MB | 22.00 MB | 11.04 MB | 11.03 MB | 20.00 MB | 20.00 MB | | after copying first data set | 11.45 MB | 11.47 MB | 22.00 MB | 22.00 MB | 376.00 B | 0.00 B | 0.00 B | 0.00 B | | after modifying first data set | 11.46 MB | 11.47 MB | 22.00 MB | 22.00 MB | 1.05 KB | 0.00 B | 0.00 B | 0.00 B | | Copy Loop 1 - Before | 11.46 MB | 11.47 MB | 22.00 MB | 22.00 MB | 424.00 B | 0.00 B | 0.00 B | 0.00 B | | Copy Loop 1 - After | 22.50 MB | 22.52 MB | 44.00 MB | 44.00 MB | 11.04 MB | 11.05 MB | 22.00 MB | 22.00 MB | | Copy Loop 2 - Before | 22.50 MB | 22.52 MB | 44.00 MB | 44.00 MB | 424.00 B | 0.00 B | 0.00 B | 0.00 B | | Copy Loop 2 - After | 33.55 MB | 33.56 MB | 66.00 MB | 66.00 MB | 11.04 MB | 11.04 MB | 22.00 MB | 22.00 MB | | Copy Loop 3 - Before | 33.55 MB | 33.56 MB | 66.00 MB | 66.00 MB | 424.00 B | 0.00 B | 0.00 B | 0.00 B | | Copy Loop 3 - After | 44.59 MB | 44.61 MB | 88.00 MB | 88.00 MB | 11.04 MB | 11.04 MB | 22.00 MB | 22.00 MB | | Copy Loop 4 - Before | 44.59 MB | 44.61 MB | 88.00 MB | 88.00 MB | 424.00 B | 0.00 B | 0.00 B | 0.00 B | | Copy Loop 4 - After | 55.63 MB | 55.65 MB | 110.00 MB | 110.00 MB | 11.04 MB | 11.04 MB | 22.00 MB | 22.00 MB | | Copy Loop 5 - Before | 55.64 MB | 55.65 MB | 110.00 MB | 110.00 MB | 424.00 B | 0.00 B | 0.00 B | 0.00 B | | Copy Loop 5 - After | 66.68 MB | 66.69 MB | 132.00 MB | 132.00 MB | 11.04 MB | 11.04 MB | 22.00 MB | 22.00 MB | | Set Loop 1 - Before | 66.68 MB | 66.69 MB | 132.00 MB | 132.00 MB | 424.00 B | 0.00 B | 0.00 B | 0.00 B | | Set Loop 1 - After | 77.72 MB | 77.74 MB | 154.00 MB | 154.00 MB | 11.04 MB | 11.04 MB | 22.00 MB | 22.00 MB | | Set Loop 2 - Before | 77.72 MB | 77.74 MB | 154.00 MB | 154.00 MB | 424.00 B | 0.00 B | 0.00 B | 0.00 B | | Set Loop 2 - After | 88.77 MB | 88.78 MB | 176.00 MB | 176.00 MB | 11.04 MB | 11.05 MB | 22.00 MB | 22.00 MB | | Set Loop 3 - Before | 88.77 MB | 88.78 MB | 176.00 MB | 176.00 MB | 424.00 B | 0.00 B | 0.00 B | 0.00 B | | Set Loop 3 - After | 99.81 MB | 99.83 MB | 198.00 MB | 198.00 MB | 11.04 MB | 11.04 MB | 22.00 MB | 22.00 MB | | Set Loop 4 - Before | 99.81 MB | 99.83 MB | 198.00 MB | 198.00 MB | 424.00 B | 0.00 B | 0.00 B | 0.00 B | | Set Loop 4 - After | 110.86 MB | 110.87 MB | 220.00 MB | 220.00 MB | 11.04 MB | 11.04 MB | 22.00 MB | 22.00 MB | | Set Loop 5 - Before | 110.86 MB | 110.87 MB | 220.00 MB | 220.00 MB | 424.00 B | 0.00 B | 0.00 B | 0.00 B | | Set Loop 5 - After | 121.90 MB | 121.92 MB | 242.00 MB | 242.00 MB | 11.04 MB | 11.04 MB | 22.00 MB | 22.00 MB | +--------------------------------+-----------+-----------+--------------+-------------+-------------+------------+--------------------+-------------------+ 7 hours ago, NotionCommotion said: Creating the initial array uses 11MB, copying it uses very little, and changing it uses 529KB. I would have expected changing it would have used the same as creating it. The reason it only goes up a bit is because the individual items between the two arrays are shared. As such the new copy only needs enough memory to store pointers to all the original row zvals + 1 more. If you did a change that would affect every row then you'd end up with more usage. 7 hours ago, NotionCommotion said: And then when I reassign $bigArray with new values, it uses 11MB which I wasn't sure whether to expect or not and this was the basis of my original question. But then I don't reassign $bigArray but pass the array directly to the class, and it also uses 11MB which I definitely did not expect and thought that it would be saved only as a reference and use very little memory. The size grows by 11MB because you're calling getData and generating a new 11MB data array. When you pass that to your DataHolder object all that happens is a new pointer to the existing zval is created. On the next loop cycle getData generates a new 11MB array with it's own zval and the $bigArray pointer is updated to point to that new zval (and no longer to the one being used in the previous DataHolder object. The exact same thing happens in the second block where you pass the data directly to the constructor, you just eliminate the bigArray variable. getData generates a new zval for the array and the new DataHolder object gets a pointer to it. Notice how both blocks see a growth of 11MB per loop. The memory usage keeps growing as the script runs because your keeping all your zvals alive by way of the DataHolder objects stored in the $dataHolders array. If you were not appending them to an array then PHP would end up just re-using the memory and your usage would stay more constant at 22MB. 11MBish for $bigArray1 and $bigArrayCopy and 11MB for $bigArray. +--------------------------------+-----------+-----------+--------------+-------------+-------------+------------+--------------------+-------------------+ | Message | Usage | Peak | Usage (Real) | Peak (Real) | Usage Delta | Peak Delta | Usage Delta (Real) | Peak Delta (Real) | +--------------------------------+-----------+-----------+--------------+-------------+-------------+------------+--------------------+-------------------+ | initial | 419.97 KB | 456.24 KB | 2.00 MB | 2.00 MB | 419.97 KB | 456.24 KB | 2.00 MB | 2.00 MB | | after creating first data set | 11.45 MB | 11.47 MB | 22.00 MB | 22.00 MB | 11.04 MB | 11.03 MB | 20.00 MB | 20.00 MB | | after copying first data set | 11.45 MB | 11.47 MB | 22.00 MB | 22.00 MB | 376.00 B | 0.00 B | 0.00 B | 0.00 B | | after modifying first data set | 11.46 MB | 11.47 MB | 22.00 MB | 22.00 MB | 1.05 KB | 0.00 B | 0.00 B | 0.00 B | | Copy Loop 1 - Before | 11.46 MB | 11.47 MB | 22.00 MB | 22.00 MB | 424.00 B | 0.00 B | 0.00 B | 0.00 B | | Copy Loop 1 - After | 22.50 MB | 22.52 MB | 44.00 MB | 44.00 MB | 11.04 MB | 11.05 MB | 22.00 MB | 22.00 MB | | Copy Loop 2 - Before | 22.50 MB | 22.52 MB | 44.00 MB | 44.00 MB | 424.00 B | 0.00 B | 0.00 B | 0.00 B | | Copy Loop 2 - After | 22.50 MB | 33.56 MB | 44.00 MB | 66.00 MB | 424.00 B | 11.04 MB | 0.00 B | 22.00 MB | | Copy Loop 3 - Before | 22.50 MB | 33.56 MB | 44.00 MB | 66.00 MB | 424.00 B | 0.00 B | 0.00 B | 0.00 B | | Copy Loop 3 - After | 22.50 MB | 33.56 MB | 44.00 MB | 66.00 MB | 744.00 B | 1.14 KB | 0.00 B | 0.00 B | | Copy Loop 4 - Before | 22.50 MB | 33.56 MB | 44.00 MB | 66.00 MB | 424.00 B | 0.00 B | 0.00 B | 0.00 B | | Copy Loop 4 - After | 22.50 MB | 33.56 MB | 44.00 MB | 66.00 MB | 424.00 B | 848.00 B | 0.00 B | 0.00 B | | Copy Loop 5 - Before | 22.50 MB | 33.56 MB | 44.00 MB | 66.00 MB | 424.00 B | 0.00 B | 0.00 B | 0.00 B | | Copy Loop 5 - After | 22.50 MB | 33.56 MB | 44.00 MB | 66.00 MB | 424.00 B | 848.00 B | 0.00 B | 0.00 B | | Set Loop 1 - Before | 22.50 MB | 33.56 MB | 44.00 MB | 66.00 MB | 424.00 B | 0.00 B | 0.00 B | 0.00 B | | Set Loop 1 - After | 22.50 MB | 33.56 MB | 44.00 MB | 66.00 MB | 424.00 B | 904.00 B | 0.00 B | 0.00 B | | Set Loop 2 - Before | 22.51 MB | 33.56 MB | 44.00 MB | 66.00 MB | 424.00 B | 0.00 B | 0.00 B | 0.00 B | | Set Loop 2 - After | 22.51 MB | 33.57 MB | 44.00 MB | 66.00 MB | 1.04 KB | 1.45 KB | 0.00 B | 0.00 B | | Set Loop 3 - Before | 22.51 MB | 33.57 MB | 44.00 MB | 66.00 MB | 424.00 B | 0.00 B | 0.00 B | 0.00 B | | Set Loop 3 - After | 22.51 MB | 33.57 MB | 44.00 MB | 66.00 MB | 424.00 B | 848.00 B | 0.00 B | 0.00 B | | Set Loop 4 - Before | 22.51 MB | 33.57 MB | 44.00 MB | 66.00 MB | 424.00 B | 0.00 B | 0.00 B | 0.00 B | | Set Loop 4 - After | 22.51 MB | 33.57 MB | 44.00 MB | 66.00 MB | 424.00 B | 848.00 B | 0.00 B | 0.00 B | | Set Loop 5 - Before | 22.51 MB | 33.57 MB | 44.00 MB | 66.00 MB | 424.00 B | 0.00 B | 0.00 B | 0.00 B | | Set Loop 5 - After | 22.51 MB | 33.57 MB | 44.00 MB | 66.00 MB | 424.00 B | 848.00 B | 0.00 B | 0.00 B | +--------------------------------+-----------+-----------+--------------+-------------+-------------+------------+--------------------+-------------------+ I'm not sure why the (Real) values do what they do. Their value depends on whether your running the script in a fresh instance of PHP (ie in CLI/CGI) or reusing an existing instance (ie, FastCGI/FPM). Quote Link to comment https://forums.phpfreaks.com/topic/309819-how-does-php-determine-to-create-a-new-copy-of-a-copied-array/#findComment-1573415 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.