Not long ago I had a debates about assignment variables to itself after some action on them.
Assign variable to itself [AI]:
echo memory_get_usage() . "\n"; // 645680
$repeatedString = str_repeat('Hello,', 10000);
echo memory_get_usage() . "\n"; // 705944, AI_delta1 = 60264
$repeatedString = explode(',', $repeatedString);
echo memory_get_usage() . "\n"; // 3337888, AI_delta2 = 2631944
echo memory_get_peak_usage() . "\n"; // AI_peak = 3401024
Assign variable to another variable [AAV]:
echo memory_get_usage() . "\n"; // 645752
$repeatedString = str_repeat('Hello,', 10000);
echo memory_get_usage() . "\n"; // 706024, AAV_delta1 = 60272
$explodedString = explode(',', $repeatedString);
echo memory_get_usage() . "\n"; // 3398256, AAV_delta2 = 2692232
echo memory_get_peak_usage() . "\n"; // AAV_peak = 3400984
I created tests of memory usage in both cases and subtract values:
AAV_delta1 - AI_delta = 8
AAV_delta2 - AI_delta2 = 60288
AAV_peak - AI_peak = -40
According to this results it doesn’t matter which approach to use, memory usage – same. It’s only a question should I use variable $repeatedString at my code below or not.
Am I right at my conclusions or my tests are not correct?
Why it happens this way?
Also a question: AAV_delta1 - AI_delta = 8, I expect it should be equal 0. Why it’s equals 8?
Note: Memory usage can vary on your system.
PHP Version: 5.3.5-1ubuntu7.11.
In AAV, there are two copies of the data, since each variable has to retain its data. They both have to persist until their respective variable is reassigned or goes out of scope.
In AI, there are temporarily two copies of the data. Once the assignment takes place, the original value is no longer needed. However, the memory it uses won’t be recovered until a garbage collection takes place.
If you check memory usage immediately after the assignment you won’t notice the difference, since there probably hasn’t been a GC yet. If you force a GC, you should see that AI uses less memory than AAV.
You can also get the same memory use improvement in AAV by unsetting the original variable after the assignment (call this AAVU):
As with AI, you will have to force a GC to notice the reduced memory use immediately.
UPDATE:
Because PHP uses reference counting for normal memory management, AI should reclaim the memory used by the string immediately. The string starts with a reference count of 1. When it gets passed to
explode(), the refcount is increased to 2 (for the reference by explode’s parameter variable). Whenexplode()returns, the parameter variable’s scope ends and the refcount returns to 1. Then when the assignment to$repeatedStringtakes place, the refcount drops to 0 and the string’s memory is reclaimed.gc_collect_cycles()is only needed to reclaim memory used by arrays and objects that are part of cycles. To see the impact of this, try the following code:Results:
For details, see PHP Garbage Collection documentation