December 04, 2008
Nick Sabalausky wrote:
> I haven't looked at any of the other responses yet, but I'd have to say "sometimes". Clearly, getting an out of memory when trying to instantiate a trivial class is nonrecoverable (unless it's happening within a section of memory-intensive code that's allowed to fail, and the rest of the program does very little allocation), but getting an out of memory when trying to allocate a 1GB buffer for video processing is certainly recoverable. 

There aren't going to be very many instances in code where one allocates 1Gb, so those can be handled as special cases.
December 04, 2008
Leandro Lucarella wrote:
> For example, I'm working on a softswitch (unfortunately no in D). Lets say
> we have a really bad moment and all the subscribers want to talk at the
> same time and we don't support that workload. Lets say our memory is
> exhausted and a new call arrive. A new allocation is done somewhere deep
> inside the call logic, so the PRE COLLECT callback is called. No memory
> can be reclaimed, so the GC runs a collection. Still no memory. POST
> COLLECT and CRISIS are called too without success. My softswitch is down,
> I lost all the current calls. This is not good for business. What I really
> wanted to do is to catch the memory error as shallow in the call logic as
> possible and drop only that current call, leaving all the current
> established calls intact.
> 
> So what can I do? Should I manually check each and every allocation in all
> the call logic? I think that's unacceptable.

That's a very good point. I need to think about that one.
December 04, 2008
== Quote from Walter Bright (newshound1@digitalmars.com)'s article
> Robert Jacques wrote:
> > Okay, while we've been talking about OutOfMemoryError there's also RangeError, AssertError, FinalizeError and SwitchError and not allowing array indexing, contract programming or switches inside a nothrow function drastically reduces their usefulness (more so than allocation, in my opinion). So at least in debug mode, the handling frame (I think) exists in order to support RangeError and AssertError errors. However, SwitchError and HiddenFuncError occur in release code, so I'm not sure if nothrow functions will not have some error handling method. (I think FinalizeError is related to allocation and therefore OutOfMemoryError)
> The idea behind Errors is that, even if you catch the exception, unwinding may not occur. Thus, your app should not be relying on destructors cleaning up properly. Catching an Error should only be used for doing things necessary before shutting down the app.

I disagree.  D is a systems app and so should not require termination on any error.  The distinction to me is that Errors require special handling if recovery is to be attempted, while it's often safe (if bad practice) to simply log Exceptions and soldier on.  That isn't to say that it's always possible (and certainly not always advisable) to recover from an Error, but I think that decision should be left up to the user.


Sean
December 04, 2008
Walter Bright wrote:
> nothrow void foo();
> 
> void bar()
> {
>     try
>     {
>     foo();
>     }
>     finally
>     {
>         will_never_execute(); // even if foo() throws
>     }
> }
> 
> because the compiler will optimize away the finally clause.

! ! !

Surely you mean "catch" rather than "finally"? I should hope that the code you have there is equivalent to:

void bar()
{
	foo();
	will_never_execute();
}

Otherwise you'd break calling code by switching a function to nothrow.
December 05, 2008
Leandro Lucarella wrote:
> For example, I'm working on a softswitch (unfortunately no in D). Lets say
> we have a really bad moment and all the subscribers want to talk at the
> same time and we don't support that workload. Lets say our memory is
> exhausted and a new call arrive. A new allocation is done somewhere deep
> inside the call logic, so the PRE COLLECT callback is called. No memory
> can be reclaimed, so the GC runs a collection. Still no memory. POST
> COLLECT and CRISIS are called too without success. My softswitch is down,
> I lost all the current calls. This is not good for business. What I really
> wanted to do is to catch the memory error as shallow in the call logic as
> possible and drop only that current call, leaving all the current
> established calls intact.
> 
> So what can I do? Should I manually check each and every allocation in all
> the call logic? I think that's unacceptable.
> 
> I think this scenario apply to each client-server application that needs
> to stay alive even with high workloads, as the expense of dropping some
> connection/client (web servers or web applications for example, as someone
> said in stackoverflow.com).

Ok, I thought about this for a while. When a virtual memory system gets close to running out of memory, it slows to a crawl and starts thrashing the disk. Other processes on the computer also start to fail by running out of memory. The program will continue to function, but it will function so poorly it might as well have aborted.

The solution is to calculate (or measure) the average memory consumption of each call. Determine the maximum memory the software should reasonably consume without thrashing, divide by the memory consumption per call, and that gives a max number of simultaneous calls. Drop calls that exceed that.

This scheme should work better, and still provides some slack if the calls dramatically exceed their average memory consumption.
December 05, 2008
Sean Kelly wrote:
> I disagree.  D is a systems app and so should not require termination on
> any error.  The distinction to me is that Errors require special handling
> if recovery is to be attempted, while it's often safe (if bad practice) to
> simply log Exceptions and soldier on.  That isn't to say that it's always
> possible (and certainly not always advisable) to recover from an Error,
> but I think that decision should be left up to the user.

If we go down that path, then nothrow functions can never allocate memory.
December 05, 2008
Christopher Wright wrote:
> Walter Bright wrote:
>> nothrow void foo();
>>
>> void bar()
>> {
>>     try
>>     {
>>     foo();
>>     }
>>     finally
>>     {
>>         will_never_execute(); // even if foo() throws
>>     }
>> }
>>
>> because the compiler will optimize away the finally clause.
> 
> ! ! !
> 
> Surely you mean "catch" rather than "finally"?

Yes. Oops!!!
December 05, 2008
Walter Bright, el  5 de diciembre a las 15:05 me escribiste:
> Sean Kelly wrote:
> >I disagree.  D is a systems app and so should not require termination on any error.  The distinction to me is that Errors require special handling if recovery is to be attempted, while it's often safe (if bad practice) to simply log Exceptions and soldier on.  That isn't to say that it's always possible (and certainly not always advisable) to recover from an Error, but I think that decision should be left up to the user.
> 
> If we go down that path, then nothrow functions can never allocate memory.

Maybe they shouldn't (and if this is true, maybe there is too little use
for nothrow :S)

-- 
Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/
----------------------------------------------------------------------------
GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145  104C 949E BFB6 5F5A 8D05)
----------------------------------------------------------------------------
Software is like sex: it's better when it's free.
	-- Linus Torvalds
December 06, 2008
Walter Bright, el  5 de diciembre a las 15:04 me escribiste:
> Leandro Lucarella wrote:
> >For example, I'm working on a softswitch (unfortunately no in D). Lets say
> >we have a really bad moment and all the subscribers want to talk at the
> >same time and we don't support that workload. Lets say our memory is
> >exhausted and a new call arrive. A new allocation is done somewhere deep
> >inside the call logic, so the PRE COLLECT callback is called. No memory
> >can be reclaimed, so the GC runs a collection. Still no memory. POST
> >COLLECT and CRISIS are called too without success. My softswitch is down,
> >I lost all the current calls. This is not good for business. What I really
> >wanted to do is to catch the memory error as shallow in the call logic as
> >possible and drop only that current call, leaving all the current
> >established calls intact.
> >So what can I do? Should I manually check each and every allocation in all
> >the call logic? I think that's unacceptable.
> >I think this scenario apply to each client-server application that needs
> >to stay alive even with high workloads, as the expense of dropping some
> >connection/client (web servers or web applications for example, as someone
> >said in stackoverflow.com).
> 
> Ok, I thought about this for a while. When a virtual memory system gets close to running out of memory, it slows to a crawl and starts thrashing the disk.  Other processes on the computer also start to fail by running out of memory. The program will continue to function, but it will function so poorly it might as well have aborted.
> 
> The solution is to calculate (or measure) the average memory consumption of each call. Determine the maximum memory the software should reasonably consume without thrashing, divide by the memory consumption per call, and that gives a max number of simultaneous calls. Drop calls that exceed that.
> 
> This scheme should work better, and still provides some slack if the calls dramatically exceed their average memory consumption.

This is not still the only possible case. See this:

luca@homero:/tmp$ cat mem.d

import core.stdc.stdio: printf;
import core.exception: OutOfMemoryError;

void main()
{
	try {
		auto x = new char[1_000_000];
	} catch (OutOfMemoryError e) {
		printf("woops! no more memory\n");
	}
}

luca@homero:/tmp$ ulimit -v 3000
luca@homero:/tmp$ dmd mem.d
luca@homero:/tmp$ ./mem
woops! no more memory

I swear my system didn't trash! =)

This is not some stupid thing just to prove you wrong. When I want my process to live for as long as possible, even in extreme situations like lack of memory, it's a very good option to do this. Because of the reasons you gave about trashing. Its more desirable that my softswitch start dropping calls a little earlier than necessary but can maintain the current ones smoothly, than let the system trash and hope for the best.

-- 
Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/
----------------------------------------------------------------------------
GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145  104C 949E BFB6 5F5A 8D05)
----------------------------------------------------------------------------
DETIENEN A PADRE, MADRE, TIOS Y ABUELOS: TODOS DEPRAVADOS
	-- Crónica TV
December 07, 2008
"Don" <nospam@nospam.com> wrote in message news:gh3et3$13tm$1@digitalmars.com...
> 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.

There ought to be a means of giving the GC a function to call whenever it's about to do its business.

> 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?
<snip>

Because there's no documented function in Phobos for checking how much memory is available, possibly?

Stewart.

-- 
My e-mail address is valid but not my primary mailbox.  Please keep replies on the 'group where everybody may benefit.