digitalmars.D - Is "Out of Memory" a recoverable error?
- Walter Bright (4/4) Dec 02 2008 I asked this over on stackoverflow.com to see what people using other
- bearophile (4/4) Dec 02 2008 In a program "Out of Memory" is recoverable, for example your program ca...
- Don (25/31) Dec 02 2008 I don't think it can be recoverable. Or rather, if it is recoverable, it...
- Robert Fraser (2/11) Dec 02 2008 I like
- Sergey Gromov (5/18) Dec 04 2008 or (3) to fail a self-contained, user initiated, "pure" operation. Like
- Stewart Gordon (11/34) Dec 06 2008 There ought to be a means of giving the GC a function to call whenever i...
- Robert Jacques (30/34) Dec 02 2008 No.
- Steven Schveighoffer (14/18) Dec 02 2008 It can be. For example, if you want to allocate a gigantic buffer to se...
- Walter Bright (5/17) Dec 02 2008 I should point out that in such cases (probing a large allocation), the
- Russell Lewis (37/42) Dec 02 2008 It seems that D has (or rather, can have) a trivial solution to this
- Jarrett Billingsley (5/11) Dec 02 2008 I've considered this as well. I've had a few occasions where I really
- Walter Bright (2/16) Dec 02 2008 I think some gc schemes implement this.
- Sean Kelly (3/14) Dec 02 2008 Interesting idea. It would certainly be easy enough to add to the GC.
- BCS (4/25) Dec 02 2008 Some sort of higher level of granularity would be nice, mostly an orderi...
- Leandro Lucarella (20/30) Dec 03 2008 I think one could benefit from manually deleting stuff, if possible. Thi...
- Sean Kelly (11/15) Dec 02 2008 Yes, but unlike some exceptions where retrying the same code may
- Kagamin (1/1) Dec 02 2008 One can get rid of OOM just by adding a couple of lines to the default m...
- Sean Kelly (4/5) Dec 02 2008 (similar to onOutOfMemoryError handler) wich does any magic wanted
- Kagamin (2/3) Dec 02 2008 I think, preventing OOM is the only possible technique to make sure you ...
- Kagamin (2/7) Dec 02 2008 magic is far more powerful than you can imagine :)
- Nick Sabalausky (8/12) Dec 03 2008 I haven't looked at any of the other responses yet, but I'd have to say
- Walter Bright (3/9) Dec 04 2008 There aren't going to be very many instances in code where one allocates...
- Leandro Lucarella (29/34) Dec 03 2008 I think all the things said in this thread makes sense (adding callbacks
- Robert Jacques (7/40) Dec 03 2008 That's a good point/use case. However,
- Robert Fraser (3/4) Dec 03 2008 Not if the function is nothrow, since the function never sets up an
- Robert Jacques (14/18) Dec 03 2008 Yeah, I'm not sure what I was thinking here.
- Walter Bright (5/14) Dec 04 2008 The idea behind Errors is that, even if you catch the exception,
- Sean Kelly (8/22) Dec 04 2008 I disagree. D is a systems app and so should not require termination on
- Walter Bright (2/8) Dec 05 2008 If we go down that path, then nothrow functions can never allocate memor...
- Leandro Lucarella (10/19) Dec 05 2008 Maybe they shouldn't (and if this is true, maybe there is too little use
- KennyTM~ (4/9) Dec 04 2008 Make a non-recoverable version as standard, and a recoverable version
- Walter Bright (22/27) Dec 04 2008 Not exactly. If you set up a try-catch, an exception handling frame is
- Christopher Wright (10/25) Dec 04 2008 ! ! !
- Walter Bright (2/22) Dec 05 2008 Yes. Oops!!!
- Leandro Lucarella (18/22) Dec 04 2008 Unfortunatelly not all designs are multithread. In my for example, we wo...
- Sean Kelly (9/32) Dec 03 2008 The same could be said of any unexpected error in such an application. ...
- Walter Bright (2/16) Dec 04 2008 That's a very good point. I need to think about that one.
- Walter Bright (13/32) Dec 05 2008 Ok, I thought about this for a while. When a virtual memory system gets
- Leandro Lucarella (31/64) Dec 06 2008 This is not still the only possible case. See this:
- Walter Bright (2/10) Dec 08 2008 I think you meant thrash, not trash!
- Leandro Lucarella (12/22) Dec 09 2008 Yes, of course =)
- Michel Fortin (22/28) Dec 04 2008 I think you got the question wrong. My answer would be: it depends.
- Michel Fortin (10/11) Dec 04 2008 I forgot to rephase explicitly the question. What I'm answering in the
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
Dec 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
Dec 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-errorI 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.
Dec 02 2008
Don wrote: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.I like
Dec 02 2008
Tue, 02 Dec 2008 14:57:49 +0100, Don wrote:Walter Bright wrote:or (3) to fail a self-contained, user initiated, "pure" operation. Like image loading process, or an expensive image editing operation, or a complex calculation. You'll find this sort of recovery in any interactive data processing application.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-errorI 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.
Dec 04 2008
"Don" <nospam nospam.com> wrote in message news:gh3et3$13tm$1 digitalmars.com...Walter Bright wrote:There ought to be a means of giving the GC a function to call whenever it's about to do its business.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-errorI 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?<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.
Dec 06 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-errorNo. 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.
Dec 02 2008
"Walter Bright" wroteI 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-errorIt 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
Dec 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.
Dec 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-errorIt 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...
Dec 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.
Dec 02 2008
Jarrett Billingsley wrote:On Tue, Dec 2, 2008 at 11:57 AM, Russell Lewis <webmaster villagersonline.com> wrote:I think some gc schemes implement this.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.
Dec 02 2008
== Quote from Russell Lewis (webmaster villagersonline.com)'s articleWalter Bright wrote:Interesting idea. It would certainly be easy enough to add to the GC. SeanI 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-errorIt 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.
Dec 02 2008
Reply to Russell,Walter Bright wrote:Some sort of higher level of granularity would be nice, mostly an ordering hint re the different stages.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-recovera ble-errorIt 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.Seems to me that with this mechanism in place, we can treat out-of-memory as an unrecoverable error. Thoughts?vote += 0.5; // nice idea, not sure it would help *me* in any way though.
Dec 02 2008
Russell Lewis, el 2 de diciembre a las 09:57 me escribiste: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.I think one could benefit from manually deleting stuff, if possible. This way, space can be found before the collection, and you saved yourself some collecting time. Manually deleting stuff could remain optional, no problem with that, so if you have data that it's not that trivial to decide if it's unused, you can just leave that work to the collector.Thoughts?Looks really interesting. This could be a perfect complement to a way to ask for memory when you expect the memory allocation to fail. -- Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/ ---------------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------------- People love to judge homeless guys. Like, your giving him money he's just gonna waste it. He's just gonna waste the money Well, he lives in a box, what do you want him to do? Save up and buy a wall unit? Take a little run to the store for a throw rug and a CD rack? He's homeless.
Dec 03 2008
== Quote from Walter Bright (newshound1 digitalmars.com)'s articleI 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-errorYes, 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
Dec 02 2008
One can get rid of OOM just by adding a couple of lines to the default malloc, that call custom handler (similar to onOutOfMemoryError handler) wich does any magic wanted, so OOM doesn't break nothrow functions, and if it's thrown, this means that recovery code has failed to recover and application exits. So nothrow protocol remains the same.
Dec 02 2008
== Quote from Kagamin (spam here.lot)'s articleOne can get rid of OOM just by adding a couple of lines to the default malloc, that call custom handler(similar to onOutOfMemoryError handler) wich does any magic wanted Endless loop. Sean
Dec 02 2008
Kagamin Wrote:One can get rid of OOM just by adding a couple of lines to the default malloc, that call custom handler (similar to onOutOfMemoryError handler) wich does any magic wanted, so OOM doesn't break nothrow functions, and if it's thrown, this means that recovery code has failed to recover and application exits. So nothrow protocol remains the same.I think, preventing OOM is the only possible technique to make sure you don't interfere with the rest of the application.
Dec 02 2008
Sean Kelly Wrote:== Quote from Kagamin (spam here.lot)'s articlemagic is far more powerful than you can imagine :)One can get rid of OOM just by adding a couple of lines to the default malloc, that call custom handler(similar to onOutOfMemoryError handler) wich does any magic wanted Endless loop.
Dec 02 2008
"Walter Bright" <newshound1 digitalmars.com> wrote in message news:gh38om$m7r$1 digitalmars.com...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-errorI 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.
Dec 03 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.
Dec 04 2008
Walter Bright, el 2 de diciembre a las 04:13 me escribiste: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-errorI think all the things said in this thread makes sense (adding callbacks to the garbage collector, adding a way to ask for memory that don't throw if the memory can't be allocated), but I think this don't cover all the possible scenarios. 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). -- Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/ ---------------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------------- PADRES DENUNCIAN QUE SU HIJA SE ESCAPO CON UN PARAGUAYITO -- Crónica TV
Dec 03 2008
On Wed, 03 Dec 2008 08:34:43 -0500, Leandro Lucarella <llucax gmail.com> wrote:Walter Bright, el 2 de diciembre a las 04:13 me escribiste:That's a good point/use case. However, 1) Many client-sever applications seperate each client into a logical thread of some kind. And inside this thread, out of memory is not recoverable. 2) One can still catch an error if need be.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-errorI think all the things said in this thread makes sense (adding callbacks to the garbage collector, adding a way to ask for memory that don't throw if the memory can't be allocated), but I think this don't cover all the possible scenarios. 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).
Dec 03 2008
Robert Jacques wrote:2) One can still catch an error if need be.Not if the function is nothrow, since the function never sets up an exception handling frame (that's the point of this topic, AFAICT).
Dec 03 2008
On Wed, 03 Dec 2008 14:47:14 -0500, Robert Fraser <fraserofthenight gmail.com> wrote:Robert Jacques wrote:Yeah, I'm not sure what I was thinking here.2) One can still catch an error if need be.Not if the function is nothrow, since the function never sets up an exception handling frame (that's the point of this topic, AFAICT).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) PS. I would class removing the exception handling frame as an optimization which is separate from the nothrow language contract feature.
Dec 03 2008
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.
Dec 04 2008
== Quote from Walter Bright (newshound1 digitalmars.com)'s articleRobert Jacques 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. SeanOkay, 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.
Dec 04 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.
Dec 05 2008
Walter Bright, el 5 de diciembre a las 15:05 me escribiste:Sean Kelly wrote: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 TorvaldsI 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.
Dec 05 2008
Robert Fraser wrote:Robert Jacques wrote:Make a non-recoverable version as standard, and a recoverable version that throws an Exception/return null as a last-resort if you really want to handle the mess (free other memories).2) One can still catch an error if need be.Not if the function is nothrow, since the function never sets up an exception handling frame (that's the point of this topic, AFAICT).
Dec 04 2008
Robert Fraser wrote:Robert Jacques wrote:Not exactly. If you set up a try-catch, an exception handling frame is set up. An exception handling frame is not necessary in order to throw an exception, it is only necessary to: 1. catch exceptions 2. unwind exceptions (run destructors) What happens if a nothrow function does throw is that your destructors and finally clauses may not get run in between the throw and the catch. For example: nothrow void foo(); void bar() { try { foo(); } finally { will_never_execute(); // even if foo() throws } } because the compiler will optimize away the finally clause.2) One can still catch an error if need be.Not if the function is nothrow, since the function never sets up an exception handling frame (that's the point of this topic, AFAICT).
Dec 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.
Dec 04 2008
Christopher Wright wrote:Walter Bright wrote:Yes. Oops!!!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"?
Dec 05 2008
Robert Jacques, el 3 de diciembre a las 09:39 me escribiste:That's a good point/use case. However, 1) Many client-sever applications seperate each client into a logical thread of some kind. And inside this thread, out of memory is not recoverable.Unfortunatelly not all designs are multithread. In my for example, we work with a single thread event loop.2) One can still catch an error if need be.I don't know what do you mean by that. If you mean you could use a try/catch block, that's no true if allocation can't throw (to be able to allocate in nothrow functions). If you mean you can use an allocation function that don't throw but report the failure in other way (like returning a null pointer), yes, as I said one, could always use that function, but is a PITA (specially for string manipulation, hashes and dynamic arrays). -- Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/ ---------------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------------- La terapia no sirve: es mucho mejor pagar para hacer las perversiones que para contarlas. -- Alberto Giordano (filósofo estilista)
Dec 04 2008
== Quote from Leandro Lucarella (llucax gmail.com)'s articleWalter Bright, el 2 de diciembre a las 04:13 me escribiste:The same could be said of any unexpected error in such an application. Assuming that you're doing call processing in a multithreaded app as opposed to dedicating a process per call (as in Erlang) then you'll have to use try/catch blocks carefully to perform the necessary cleanup at each stage, re-throwing exceptions you don't intend to handle.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-errorI think all the things said in this thread makes sense (adding callbacks to the garbage collector, adding a way to ask for memory that don't throw if the memory can't be allocated), but I think this don't cover all the possible scenarios. 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.Agreed. The point of exceptions is to avoid the need to verify the result of every operation and to avoid duplication of recovery code. Sean
Dec 03 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.
Dec 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. 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.
Dec 05 2008
Walter Bright, el 5 de diciembre a las 15:04 me escribiste:Leandro Lucarella wrote: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 TVFor 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.
Dec 06 2008
Leandro Lucarella wrote: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.I think you meant thrash, not trash!
Dec 08 2008
Walter Bright, el 8 de diciembre a las 17:35 me escribiste:Leandro Lucarella wrote:Yes, of course =) (I'm not a native english speaker, so excuse me for this error, and that will come in the future ;) -- Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/ ---------------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------------- "Lidiar" no es lo mismo que "holguear"; ya que "lidiar" es relativo a "lidia" y "holguear" es relativo a "olga". -- Ricardo VaporesoI 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.I think you meant thrash, not trash!
Dec 09 2008
On 2008-12-02 07:13:12 -0500, Walter Bright <newshound1 digitalmars.com> said: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-errorI think you got the question wrong. My answer would be: it depends. I think you could make this simple reasonable rule: anything that would throw an exception in a nothrow function yeilds a fatal error. When you want to catch out of memory errors (or any other error for that matter), just avoid nothrow. How does that sound? It sounds to me like nothrow functions are going to be dangerous in big applications since it could make some distant part of an app crash the whole thing. At least, you should be allowed to handle those exceptions (out of memory, range error, etc) in an error handler function before it kills the current thread. But even with that it'll be hard to guarenty proper cleanup; that's why I'm saying it makes nothrow dangerous. Note however that you can't guarenty proper cleanup either in case of division by zero or invalid pointer dereferencing, so by allowing dynamic allocation you're not extending the problem very much. It'd be great if those could throw exceptions when not in a nothrow function. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Dec 04 2008
On 2008-12-04 07:34:18 -0500, Michel Fortin <michel.fortin michelf.com> said:I think you got the question wrong. My answer would be: it depends.I forgot to rephase explicitly the question. What I'm answering in the parent post is: "When should an out of memory exception be a fatal error?" And the answer I give in the parent post would be: "When you're in a nothrow function!" -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Dec 04 2008