December 02, 2008
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
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
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
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
"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
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
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
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
== 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
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