On 19/05/2015 00:07, Christoph Becker wrote:
> What happens if the soft limit is exhausted, but the GC can free only a
> little memory?  That might trigger the GC shortly afterwards again and
> again.

The usual way to stop this sort of flapping is to set the point at
which the alarm gets reset to be significantly lower than the point at
which an alarm is triggered in the first place. And as Rowan said, the
current situation is that applications just crash when they run out of
memory, so a little slow but not 50x response would still be better.

On 19 May 2015 at 00:21, Rowan Collins <rowan.coll...@gmail.com> wrote:
> Dynamically adjusting the limit would be no help, because if you're that
> hard up against the limit, your only hope is to gracefully end the process 
> anyway.

To be clear - we don't really have hard memory limits in PHP. We have
a limit that users specify in an ini file, but this can be overridden
in a script by just calling ini_set('memory_limit', $moreMemory);. The
only real hard limit is when malloc starts failing, at which point all
hope is lost.


So, I think what would be needed for graceful handling of memory usage is:

* Allow users to specify programmatically (i.e. not in the ini file)
memory trigger limits and a callable for each of those limits.

* When one limit is reached, set the memory limit to the next higher
one, and call the callable associated with the memory level just
reached, at the next appropriate place in the engine. I don't think
checking after each allocation would be feasible as it would be too
nasty to code, as well as having to much of a performance impact.
Instead this seems to be more likely to work if it was tied into the
'tick' functionality.

* When there are no more memory limits left, or a limit would be
higher than memory_limit, trigger the current behaviour for when the
application has run out of memory (i.e. abort the application).

* When gc_collect_cycles is called (and potentially other functions),
at the end of that function check whether the amount of memory being
used is less than reset level for each trigger. If so reduce the
current memory limit to the lowest trigger level.

The reason for having multiple limits is that people will want their
code to do different things at the different limits. For example,
imagine someone who has some PHP code serving a simple API that for
business reasons needs to respond quickly, which uses typically uses
4MB to serve a request.

It would be reasonable for them to have the trigger levels of:

8MB - Log that this request used more memory than average, and someone
should investigate it at some point.

32MB - Log this request is using 8 times as much memory as usual and
someone needs to investigate it reasonably urgently, and trigger
gc_collect_cycles. gc_collect_cycles is a relatively slow function,
and so this will make the request slower than desired.

64MB - Throw an exception and cleanly shut down the application.

And a max memory_limit of 128MB where the application does the current
behaviour of falling over and dying.

I'll wait for some feedback, then write an RFC unless someone can say
something that would be significantly better, or why the above would
be either bad or technically unfeasible.

cheers
Dan

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

Reply via email to