View mode: basic / threaded / horizontal-split · Log in · Help
December 02, 2008
Is "Out of Memory" a recoverable error?
I asked this over on stackoverflow.com to see what people using other 
languages have to say, as well as the D community. The reason I ask is 
to see if memory allocation can be allowed in functions marked "nothrow".

http://stackoverflow.com/questions/333736/is-out-of-memory-a-recoverable-error
December 02, 2008
Re: Is "Out of Memory" a recoverable error?
In a program "Out of Memory" is recoverable, for example your program can use several caches, buffers, and it can use data already present on disk too, or data that can be moved on disk now.
A good program when finds an out of memory situation can clear its caches, delete not essential data structures, and save some data on disk, to free some RAM. (All this can be useful in operating systems with virtual memory too).

Bye,
bearophile
December 02, 2008
Re: Is "Out of Memory" a recoverable error?
Walter Bright wrote:
> I asked this over on stackoverflow.com to see what people using other 
> languages have to say, as well as the D community. The reason I ask is 
> to see if memory allocation can be allowed in functions marked "nothrow".
> 
> http://stackoverflow.com/questions/333736/is-out-of-memory-a-recoverable-error 
> 
I don't think it can be recoverable. Or rather, if it is recoverable, it 
shouldn't have happened in the first place.

As far as I can tell, the only thing you could do to recover from an 
out-of-memory condition is (1) to free some memory, or (2) to switch to 
an algorithm which doesn't need as much memory.

Strategy (1):
Windows used to have a WM_COMPACTING message (maybe it still does) which 
was sent when the system was running low on memory. In D, you could 
imagine a similar sort of system callback, which is called when memory 
is short -- it means, free some memory now, otherwise you'll get an out 
of memory error.
This is much simpler and more powerful than catching an 
OutOfMemoryException, freeing some memory, and then repeating what you 
were doing.

Strategy (2):
If you've got a second algorithm to use, why weren't you checking 
available memory, and choosing the correct algorithm in the first place?

I don't think either of these strategies make sense. The technique of 
catching exceptions works because you have locality of reference of 
almost all resources. If you get a FileException, the bit of code which 
deals with that particular file is small, and you can unroll the call 
stack to get past it. But memory usage is a whole-program thing. The 
biggest unnecessary memory allocation might be a completely unrelated 
part of the program.
December 02, 2008
Re: Is "Out of Memory" a recoverable error?
On Tue, 02 Dec 2008 07:13:12 -0500, Walter Bright  
<newshound1@digitalmars.com> wrote:
> I asked this over on stackoverflow.com to see what people using other  
> languages have to say, as well as the D community. The reason I ask is  
> to see if memory allocation can be allowed in functions marked "nothrow".
>
> http://stackoverflow.com/questions/333736/is-out-of-memory-a-recoverable-error

No.
An out of memory error from the GC is should not generally be recoverable  
inside of the current thread. (Recoverable thread (user or kernel)  
creation and termination should be supported though)

Regarding the counter examples:
I'm currently working on a D project which uses NVIDIA's CUDA platform for  
GPU computing. Instead of manually managing GPU memory, I've created proxy  
objects to leverage the D's GC. So when the GPU returns an out of memory  
error, I run a full collect and only raise an exception if it fails a  
second time. But, this isn't really and example of out of memory recovery,  
and more one of GC integration. The other examples of recovery (caches,  
free-lists, stacks/hashes without auto-shrinking, etc) are all structures  
that have their own methods of collecting/compacting memory which are  
separate from the GC and tend not to be local to the allocating function.
So people might implement something like the following:

T new2(T)( lazy T old_new ) {
    T obj;
    try{
        obj = old_new;
    }catch(OutOfMemoryException oome) {
        foreach(compact; Global_List_Of_Delegates_From_Compatible_Objects)
            compact();
        obj = old_new;
    }
    return obj;
}

Which is a decent argument for adding support for  
registering/unregistering self-collecting/compacting objects to the GC.
December 02, 2008
Re: Is "Out of Memory" a recoverable error?
"Walter Bright" wrote
>I asked this over on stackoverflow.com to see what people using other 
>languages have to say, as well as the D community. The reason I ask is to 
>see if memory allocation can be allowed in functions marked "nothrow".
>
> http://stackoverflow.com/questions/333736/is-out-of-memory-a-recoverable-error

It can be.  For example, if you want to allocate a gigantic buffer to see if 
you can load a file, you may catch for failure, and display an appropriate 
message to the user on failure.  The application could still continue to 
run.  I think the difference between recoverable and non-recoverable is the 
size of the allocation.  If the size is sufficiently large enough, you can 
still have memory to deal with the failure.  If allocating 16 bytes gives 
you a failure, then may not be able to do much to get around it.

In most cases, an out of memory failure is a non-recoverable error.  My 
thoughts are, add a recoverable allocate function to the GC.  If one wants a 
recoverable memory error, he must call that function to allocate.  Don't 
allow that function in nothrow functions, but allow standard (non 
recoverable) memory allocation to be called.

-Steve
December 02, 2008
Re: Is "Out of Memory" a recoverable error?
Steven Schveighoffer wrote:
> It can be.  For example, if you want to allocate a gigantic buffer to see if 
> you can load a file, you may catch for failure, and display an appropriate 
> message to the user on failure.  The application could still continue to 
> run.  I think the difference between recoverable and non-recoverable is the 
> size of the allocation.  If the size is sufficiently large enough, you can 
> still have memory to deal with the failure.  If allocating 16 bytes gives 
> you a failure, then may not be able to do much to get around it.

I should point out that in such cases (probing a large allocation), the 
error recovery is very local. I.e. there's no need for throwing an 
exception and then recovering in some arbitrary user code way up the stack.

> In most cases, an out of memory failure is a non-recoverable error.  My 
> thoughts are, add a recoverable allocate function to the GC.  If one wants a 
> recoverable memory error, he must call that function to allocate.  Don't 
> allow that function in nothrow functions, but allow standard (non 
> recoverable) memory allocation to be called.

I think this may be the best strategy.
December 02, 2008
Re: Is "Out of Memory" a recoverable error?
Walter Bright wrote:
> I asked this over on stackoverflow.com to see what people using other 
> languages have to say, as well as the D community. The reason I ask is 
> to see if memory allocation can be allowed in functions marked "nothrow".
> 
> http://stackoverflow.com/questions/333736/is-out-of-memory-a-recoverable-error 

It seems that D has (or rather, can have) a trivial solution to this 
problem.  Allow programs to register with the GC when they have memory 
which can be easily freed (caches and such).  Then you can make "out of 
memory" a non-recoverable error, since it only hits when we fail to 
recover enough.

It seems to me that there are 3 different types of callbacks that can be 
registered: pre-scan, post-scan, and crisis.

PRE-SCAN

Before the mark & sweep runs, *every one* of these callbacks is called. 
 These are for things which the program can give up with very little 
cost, such as emptying free pools in allocators.  Since this happens 
before the scan, you do *not* have to use explicit "delete"s; you can 
just drop references as normal.  After all of these callbacks are 
called, the mark & sweep runs, and we hope that it will find some 
newly-discarded regions.

POST-SCAN

This is for things which we typically don't want to give up, but which 
we might relinquish if the only alternative would be getting more memory 
from the OS.  For instance, caches of things read from disk.  In this 
case, callbacks must explicitly delete things (since the scanner has 
already run).  The GC will call each of these in turn, but will stop if 
and when enough (contiguous) memory is freed to perform the allocation 
that the GC is trying to perform.  If the GC goes through the entire 
list without finding enough, it will ask the OS for more memory.

CRISIS

This is a set of callbacks which represent things which we would only 
discard in a true crisis, such as caches which would be time-consuming 
to rebuild.  These are called only if the OS refuses to give us more 
memory.  Again, you have to explicitly delete, and the GC will stop 
calling if and when it finds enough free memory.



Seems to me that with this mechanism in place, we can treat 
out-of-memory as an unrecoverable error.

Thoughts?

P.S. It would be nice to also have callbacks that were called when the 
OS started page swapping, or callbacks to deal with fragmentation.  But 
that is something to consider some other time...
December 02, 2008
Re: Is "Out of Memory" a recoverable error?
On Tue, Dec 2, 2008 at 11:57 AM, Russell Lewis
<webmaster@villagersonline.com> wrote:
> It seems that D has (or rather, can have) a trivial solution to this
> problem.  Allow programs to register with the GC when they have memory which
> can be easily freed (caches and such).  Then you can make "out of memory" a
> non-recoverable error, since it only hits when we fail to recover enough.
>
> ...
>
> Thoughts?

I've considered this as well.  I've had a few occasions where I really
wanted something to trigger upon garbage collection.  Conveniently,
this is also dead easy to implement.
December 02, 2008
Re: Is "Out of Memory" a recoverable error?
== Quote from Walter Bright (newshound1@digitalmars.com)'s article
> I asked this over on stackoverflow.com to see what people using other
> languages have to say, as well as the D community. The reason I ask is
> to see if memory allocation can be allowed in functions marked "nothrow".
> http://stackoverflow.com/questions/333736/is-out-of-memory-a-recoverable-error

Yes, but unlike some exceptions where retrying the same code may
succeed, an out of memory condition almost always requires explicit
handling for recovery.  Because it's not typical for an application to
explicitly handle memory errors however, I think an OOME can
generally be treated as an unrecoverable error.

I suppose it's worth mentioning that the OOME exception class derives
from Error now in D 2.0, for the reasons mentioned above.  Not sure
if you'd simply like to judge recoverability based on the superclass
choice, but it would be a simple enough rule to follow.


Sean
December 02, 2008
Re: Is "Out of Memory" a recoverable error?
Jarrett Billingsley wrote:
> On Tue, Dec 2, 2008 at 11:57 AM, Russell Lewis
> <webmaster@villagersonline.com> wrote:
>> It seems that D has (or rather, can have) a trivial solution to this
>> problem.  Allow programs to register with the GC when they have memory which
>> can be easily freed (caches and such).  Then you can make "out of memory" a
>> non-recoverable error, since it only hits when we fail to recover enough.
>>
>> ...
>>
>> Thoughts?
> 
> I've considered this as well.  I've had a few occasions where I really
> wanted something to trigger upon garbage collection.  Conveniently,
> this is also dead easy to implement.

I think some gc schemes implement this.
« First   ‹ Prev
1 2 3 4 5
Top | Discussion index | About this forum | D home