On 11 March 2015 at 21:44, Dmitry Stogov <dmi...@zend.com> wrote:
> Hi,
>
> Improvement ideas are welcome...


Hi Dmitry,

The idea was raised before of having both soft and hard limits for the
memory consumption and time limits, and to trigger a user defined
callback when the soft limit was reached.

This would be beneficial in a couple of ways.

i) It allows people to detect that their application is consuming more
memory/time than they would like, but not enough to cause stability
issues. This would be useful in production where you don't want to
make a request fail unless you absolutely have to.

ii) It allows them to decide exactly what action to take. Sometimes
it's fine to terminate requests straight away, other times people
would want to do some cleanup before terminating.

Additionally being able to call gc_collect_cycles() in the callback
would sometimes release enough memory to bring the memory used to back
under the soft limit and so allow processing to continue. Ironically,
this seems to be an issue when writing efficient PHP code. Due to the
way the garbage collector only collects cycles rarely, if you have
very large variables compared to typical code, you can easily
encounter a situation where the total memory that is still being
referenced is small, but there is still a huge amount being held in
cycles.

The code below shows this happening:
    With gc_collect_cycles called: peak memory = 786kB
    Without gc_collect_cycles called: Allowed memory size of 67108864
bytes exhausted

i.e. 95% of memory allocated isn't being used and could be freed, but
hasn't because the number of GC objects didn't reach 10,000 and so the
gc_collect_cycles didn't kick in automatically.

cheers
Dan



<?php


$performGC = false;

if ($performGC) {
    echo "GC collection will be done - app should not crash.\n";
}
else {
    echo "GC collection won't be done - app should crash.\n";
}
$dataSizeInKB = 128;

//Change this line if you tweak the parameters above.
ini_set('memory_limit', "64M");

$memData = '';

for ($y=0 ; $y<$dataSizeInKB ; $y++) {
    for ($x=0 ; $x<32 ; $x++) { //1kB
        $memData .= md5(time() + (($y * 32) + $x));
    }
}

file_put_contents("memdata.txt", $memData);

// This function creates a cyclic variable loop
function useSomeMemory($x) {
    $data = [];
    $data[$x] = file_get_contents("memdata.txt");
    $data[$x + 1] = &$data;
};


for($x=0 ; $x<1000 ; $x++) {
    useSomeMemory($x);
    if ($performGC == true) {
        gc_collect_cycles();
    }
}

printf(
    "\nused: %10d | allocated: %10d | peak: %10d\n",
    memory_get_usage(),
    memory_get_usage(true),
    memory_get_peak_usage(true)
);

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to