digitalmars.D.learn - Understanding the GC
- Jeremy DeHaan (22/22) Jan 29 2013 I've been reading TDPL book and was also reading some posts on
- Mike Parker (60/78) Jan 30 2013 That's not quite correct. When the object is collected, its
- Mike Parker (12/12) Jan 30 2013 The take-home point of all of this is that you shouldn't rely on
- monarch_dodra (28/45) Jan 30 2013 To add to that, you also have to keep in mind that when the
- Maxim Fomin (9/23) Jan 30 2013 I found calling member class references as nested classes
- monarch_dodra (5/29) Jan 30 2013 No. What gave you that idea? I said the "reference" a will be
- Maxim Fomin (4/39) Jan 30 2013 English is not native for me. Sometimes non-natives misunderstand
- monarch_dodra (2/4) Jan 30 2013 My apologies.
- Jeremy DeHaan (9/20) Jan 31 2013 So there is no guarantee at all that a destructor will be called
- Steven Schveighoffer (18/39) Jan 31 2013 I'm pretty sure all GCs do not have a guarantee of running all
- Jeremy DeHaan (9/55) Jan 31 2013 This makes a whole lot of sense to me. I never realized that a GC
- monarch_dodra (18/35) Jan 31 2013 I've actually run into this very issue: I was iterating on files,
- Steven Schveighoffer (10/45) Feb 01 2013 Actually, that's a different problem. File is a struct, and structs do ...
- monarch_dodra (8/64) Feb 01 2013 Oh. Wow. That's news to me.
- Steven Schveighoffer (17/31) Feb 01 2013 Dynamic arrays do clean up the array memory. For arrays of objects, or ...
- FG (9/15) Feb 01 2013 So currently the only way to make a struct's destructor work when the st...
- Sean Kelly (21/43) Feb 01 2013 ated memory. Because of that, it's generally not used.
- Steven Schveighoffer (10/18) Jan 31 2013 This isn't quite accurate.
- Sean Kelly (16/27) Jan 31 2013 GG.reserve can be handy for this. It tells the GC to pre allocate a bloc...
I've been reading TDPL book and was also reading some posts on these forums about the GC, but I wanted to clarify a few things to make sure I am understanding correctly. From what I understand, when an object is recovered by the GC, the destructor may or may not be called. Why is that? Is it for performace reasons? What about the destructors of objects that the original object contained? Are they called when the item finally get's taken care of by the GC, or when the object is originally recovered by the GC? My other question is, at the end of the program will GC go through every object it knows still holds memory and call their destructors? My guess is that it does so that the GC ensures all memory is successfully released before the program ends. I just want to make sure since in http://dlang.org/class.html, it says, "The garbage collector is not guaranteed to run the destructor for all unreferenced objects." What exactly is an unreferenced object? Some other questions: At what point is the GC called to do it's thing while the program is running? Is it at certain intervals or is it when the program's memory reaches a certain point? Thanks very much for all the help!
Jan 29 2013
On Wednesday, 30 January 2013 at 06:00:44 UTC, Jeremy DeHaan wrote:From what I understand, when an object is recovered by the GC, the destructor may or may not be called. Why is that? Is it forThat's not quite correct. When the object is collected, its destructor will be called. But you have no control over when or if it will happen during runtime. More on this below in relation to your question about unreferenced objects.performace reasons? What about the destructors of objects that the original object contained? Are they called when the item finally get's taken care of by the GC, or when the object is originally recovered by the GC?Destructors of members will not be called when an object is collected. Only that of the object itself. But, there's no guarantee that any member references will still be valid when the object's destructor is called. See below for more.My other question is, at the end of the program will GC go through every object it knows still holds memory and call their destructors? My guess is that it does so that the GC ensuresYes.all memory is successfully released before the program ends. I just want to make sure since in http://dlang.org/class.html, it says, "The garbage collector is not guaranteed to run the destructor for all unreferenced objects." What exactly is an unreferenced object?A "referenced" object is one that is still in use by the program. Example: auto mc = new MyClass; // Here, there is exactly one reference to the MyClass instance // and it is still active. // But if i do this... auto mc2 = mc; // Now there are 2 references to the same instance. // Set one to null. mc = null; // Now there is only one reference. Null it... mc2 = null; // Now all references to the original instance are invalid, // so the object is unreachable by the program, so it is an // unreferenced object. The GC can only collect objects that it can be sure are unreferenced. Sometimes it can't be sure, in which case that particular object won't be collected during run time. For the objects that are determined to be collectable, there's no way to guarantee that any one of them will be collected in any given collection cycle. Because of that, you cannot rely on the order of destruction. Consider: class Foo {} class Bar { Foo f; } Bar b = new Bar; b.f = new Foo; Given that b.f is the only reference to this Foo instance, then this instance of Foo will become unreferenced at the same time that the instance of Bar does. But, again, we cannot rely on the Bar instance being collected and destructed before the Foo instance. So if you have a Bar destructor that tries to access a member in f, then you would get a crash some of the time. Worse, what if there were more references to the Foo instance outside of Bar that haven't been released yet? If you tried to destroy f from the Bar destructor, or perhaps call some sort of cleanup method to release system resources that f controls, you'll get a crash somewhere else in the program when another bit of code tries to access the no longer valid reference. That would likely be a marathon debugging session, because most of the time you don't expect that sort of thing.Some other questions: At what point is the GC called to do it's thing while the program is running? Is it at certain intervals or is it when the program's memory reaches a certain point?My understanding is that the current implementation only runs collections when memory is allocated. Meaning, when you allocate a new object instance, or cause memory to be allocated via some built-in operations (on arrays, for example), the GC will check if anything needs to be collected and will do it at that time. I don't know if it's run on every allocation, or only when certain criteria or met, and I really don't care. That's an implementation detail. The D language itself does not specify any of that.
Jan 30 2013
The take-home point of all of this is that you shouldn't rely on destructors for resource deallocation. You could do it in by manually destructing objects when you are finished with them (via the destroy() method), but then you have to be extra careful about class members, ownership, order of destruction, and all of that. I find that it's much simpler if I give each of my objects a specific cleanup method that releases its own resources. When an object is no longer needed, I call its cleanup method and clear any references to it. This ensures that system resources or whatever are released in a predictable order and I don't run into odd crashes from trying to release something that's no longer valid. The GC takes care of the rest.
Jan 30 2013
On Wednesday, 30 January 2013 at 08:15:15 UTC, Mike Parker wrote:On Wednesday, 30 January 2013 at 06:00:44 UTC, Jeremy DeHaan wrote:To add to that, you also have to keep in mind that when the program terminates (even legally), instead of running a *full* collect cycle, the program just leaves, and lets the OS clear any allocated memory. This is both faster, and safer. What this means is that while there is a guarantee that "collection=>destruction", there is no guarantee that actual collection will happen. If you absolutely must be sure that something allocated gets *destroyed*, either destroy it yourself via an explicit call, or bind it to a stack based RAII scheme, possibly with reference counting.From what I understand, when an object is recovered by the GC, the destructor may or may not be called. Why is that? Is it forThat's not quite correct. When the object is collected, its destructor will be called. But you have no control over when or if it will happen during runtime. More on this below in relation to your question about unreferenced objects.Just to be clear, I suppose you (both) are talking about "member references"? EG: Nested classes? Destroying an object 100% guarantees its member destroyers are also called, outer to inner, first in first out, as part of the destruction process. The thing is that when you store a "class reference" then you call the destructor of the reference itself. References being glorified pointers, it basically means it does nothing. //---- struct S{} class A{} struct/class SA { S s; //destroying this means ~S gets called. A a; //"destroying" this means doing "a = null". }performace reasons? What about the destructors of objects that the original object contained? Are they called when the item finally get's taken care of by the GC, or when the object is originally recovered by the GC?Destructors of members will not be called when an object is collected. Only that of the object itself. But, there's no guarantee that any member references will still be valid when the object's destructor is called. See below for more.
Jan 30 2013
On Wednesday, 30 January 2013 at 10:29:26 UTC, monarch_dodra wrote:On Wednesday, 30 January 2013 at 08:15:15 UTC, Mike Parker wrote:I found calling member class references as nested classes confusing - they are very different.Destructors of members will not be called when an object is collected. Only that of the object itself. But, there's no guarantee that any member references will still be valid when the object's destructor is called. See below for more.Just to be clear, I suppose you (both) are talking about "member references"? EG: Nested classes?Destroying an object 100% guarantees its member destroyers are also called, outer to inner, first in first out, as part of the destruction process. The thing is that when you store a "class reference" then you call the destructor of the reference itself. References being glorified pointers, it basically means it does nothing.Are you implying that in following code snippet: class A { ~this() { ... } } class B { A a; ~this() { ... } } destructor of A will be always called after B, so "a" member is always accessible in B's dtor?
Jan 30 2013
On Wednesday, 30 January 2013 at 11:57:01 UTC, Maxim Fomin wrote:On Wednesday, 30 January 2013 at 10:29:26 UTC, monarch_dodra wrote:No. What gave you that idea? I said the "reference" a will be destroyed (set to null). The actual referenced "class instance" may or may not be destroyed by then. The class instance of A itself is not a member of B.On Wednesday, 30 January 2013 at 08:15:15 UTC, Mike Parker wrote:I found calling member class references as nested classes confusing - they are very different.Destructors of members will not be called when an object is collected. Only that of the object itself. But, there's no guarantee that any member references will still be valid when the object's destructor is called. See below for more.Just to be clear, I suppose you (both) are talking about "member references"? EG: Nested classes?Destroying an object 100% guarantees its member destroyers are also called, outer to inner, first in first out, as part of the destruction process. The thing is that when you store a "class reference" then you call the destructor of the reference itself. References being glorified pointers, it basically means it does nothing.Are you implying that in following code snippet: class A { ~this() { ... } } class B { A a; ~this() { ... } } destructor of A will be always called after B, so "a" member is always accessible in B's dtor?
Jan 30 2013
On Wednesday, 30 January 2013 at 12:08:07 UTC, monarch_dodra wrote:On Wednesday, 30 January 2013 at 11:57:01 UTC, Maxim Fomin wrote:English is not native for me. Sometimes non-natives misunderstand the meaning of the words.On Wednesday, 30 January 2013 at 10:29:26 UTC, monarch_dodra wrote:No. What gave you that idea? I said the "reference" a will be destroyed (set to null). The actual referenced "class instance" may or may not be destroyed by then. The class instance of A itself is not a member of B.On Wednesday, 30 January 2013 at 08:15:15 UTC, Mike Parker wrote:I found calling member class references as nested classes confusing - they are very different.Destructors of members will not be called when an object is collected. Only that of the object itself. But, there's no guarantee that any member references will still be valid when the object's destructor is called. See below for more.Just to be clear, I suppose you (both) are talking about "member references"? EG: Nested classes?Destroying an object 100% guarantees its member destroyers are also called, outer to inner, first in first out, as part of the destruction process. The thing is that when you store a "class reference" then you call the destructor of the reference itself. References being glorified pointers, it basically means it does nothing.Are you implying that in following code snippet: class A { ~this() { ... } } class B { A a; ~this() { ... } } destructor of A will be always called after B, so "a" member is always accessible in B's dtor?
Jan 30 2013
On Wednesday, 30 January 2013 at 12:17:33 UTC, Maxim Fomin wrote:English is not native for me. Sometimes non-natives misunderstand the meaning of the words.My apologies.
Jan 30 2013
On Wednesday, 30 January 2013 at 10:29:26 UTC, monarch_dodra wrote:To add to that, you also have to keep in mind that when the program terminates (even legally), instead of running a *full* collect cycle, the program just leaves, and lets the OS clear any allocated memory. This is both faster, and safer. What this means is that while there is a guarantee that "collection=>destruction", there is no guarantee that actual collection will happen. If you absolutely must be sure that something allocated gets *destroyed*, either destroy it yourself via an explicit call, or bind it to a stack based RAII scheme, possibly with reference counting.So there is no guarantee at all that a destructor will be called even at the end of the program? Because there is an example in the book using a class destructor to free allocated data. I definitely understand now about how not to rely on a destructor to free up memory during runtime, but it seems counterintuitive to have the ability to write a destructor with no guarantee it would ever be called even at cleanup.
Jan 31 2013
On Thu, 31 Jan 2013 18:27:59 -0500, Jeremy DeHaan <dehaan.jeremiah gmail.com> wrote:On Wednesday, 30 January 2013 at 10:29:26 UTC, monarch_dodra wrote:I'm pretty sure all GCs do not have a guarantee of running all destructors. I think D's GC makes a good effort to do so.To add to that, you also have to keep in mind that when the program terminates (even legally), instead of running a *full* collect cycle, the program just leaves, and lets the OS clear any allocated memory. This is both faster, and safer. What this means is that while there is a guarantee that "collection=>destruction", there is no guarantee that actual collection will happen. If you absolutely must be sure that something allocated gets *destroyed*, either destroy it yourself via an explicit call, or bind it to a stack based RAII scheme, possibly with reference counting.So there is no guarantee at all that a destructor will be called even at the end of the program? Because there is an example in the book using a class destructor to free allocated data.I definitely understand now about how not to rely on a destructor to free up memory during runtime, but it seems counterintuitive to have the ability to write a destructor with no guarantee it would ever be called even at cleanup.A destructor should ONLY be used to free up resources other than GC allocated memory. Because of that, it's generally not used. It should be used almost as a "last resort". For example, a class that holds a file descriptor should have both a destructor (which closes the descriptor) and a manual close method. The former is to clean up the file descriptor in case nobody thought to close it manually before all references were gone, and the latter is because file descriptors are not really managed by the GC, and so should be cleaned up when they are no longer used. This kind of gives us a paradox, since the class is managed via the GC, how do you know it's no longer used (that is, how do you know this is the last reference to it)? That is really up to the application design. But I wouldn't recommend relying on the GC to clean up your descriptors. -Steve
Jan 31 2013
On Thursday, 31 January 2013 at 23:53:26 UTC, Steven Schveighoffer wrote:On Thu, 31 Jan 2013 18:27:59 -0500, Jeremy DeHaan <dehaan.jeremiah gmail.com> wrote:This makes a whole lot of sense to me. I never realized that a GC could be imperfect in this regard. I also don't know much about GC design and implementation, but that was the purpose of this thread! I definitely like the idea of having a manual way of cleaning up and a destructor as a back up for times such as these. Thanks for all the help guys! I learned a lot!On Wednesday, 30 January 2013 at 10:29:26 UTC, monarch_dodra wrote:I'm pretty sure all GCs do not have a guarantee of running all destructors. I think D's GC makes a good effort to do so.To add to that, you also have to keep in mind that when the program terminates (even legally), instead of running a *full* collect cycle, the program just leaves, and lets the OS clear any allocated memory. This is both faster, and safer. What this means is that while there is a guarantee that "collection=>destruction", there is no guarantee that actual collection will happen. If you absolutely must be sure that something allocated gets *destroyed*, either destroy it yourself via an explicit call, or bind it to a stack based RAII scheme, possibly with reference counting.So there is no guarantee at all that a destructor will be called even at the end of the program? Because there is an example in the book using a class destructor to free allocated data.I definitely understand now about how not to rely on a destructor to free up memory during runtime, but it seems counterintuitive to have the ability to write a destructor with no guarantee it would ever be called even at cleanup.A destructor should ONLY be used to free up resources other than GC allocated memory. Because of that, it's generally not used. It should be used almost as a "last resort". For example, a class that holds a file descriptor should have both a destructor (which closes the descriptor) and a manual close method. The former is to clean up the file descriptor in case nobody thought to close it manually before all references were gone, and the latter is because file descriptors are not really managed by the GC, and so should be cleaned up when they are no longer used. This kind of gives us a paradox, since the class is managed via the GC, how do you know it's no longer used (that is, how do you know this is the last reference to it)? That is really up to the application design. But I wouldn't recommend relying on the GC to clean up your descriptors. -Steve
Jan 31 2013
On Thursday, 31 January 2013 at 23:53:26 UTC, Steven Schveighoffer wrote:A destructor should ONLY be used to free up resources other than GC allocated memory. Because of that, it's generally not used. It should be used almost as a "last resort". For example, a class that holds a file descriptor should have both a destructor (which closes the descriptor) and a manual close method. The former is to clean up the file descriptor in case nobody thought to close it manually before all references were gone, and the latter is because file descriptors are not really managed by the GC, and so should be cleaned up when they are no longer used. This kind of gives us a paradox, since the class is managed via the GC, how do you know it's no longer used (that is, how do you know this is the last reference to it)? That is really up to the application design. But I wouldn't recommend relying on the GC to clean up your descriptors. -SteveI've actually run into this very issue: I was iterating on files, opening them, and placing the descriptor in GC-allocated RAII data. I can't remember if class or struct, but not a big issue. Come to think about it, I think I was using "File", but allocating them because I thought they were classes `auto f = new File("my file", "r")`. After running for a second, my program halts, because an exception was thrown trying to open a new file: "Cannot open file: Too many open file handles". It was basically: Sure, the GC will destroy and close files for you... if you forget... eventually... I ended up closing them in scope(exit) blocks. Problem immediately solved. Or I could have stopped allocating my File's on the heap. Either way, it shows you shouldn't rely on the GC for deterministic destruction.
Jan 31 2013
On Fri, 01 Feb 2013 02:07:00 -0500, monarch_dodra <monarchdodra gmail.com> wrote:On Thursday, 31 January 2013 at 23:53:26 UTC, Steven Schveighoffer wrote:Actually, that's a different problem. File is a struct, and structs do NOT have their destructor run by the GC. Only Objects do. This is a GC limitation, since structs do not contain a pointer to their typeinfo like classes do, and there is no provision for storing a pointer to the typeinfo of a block. It could be fixed by a more precise GC. AIUI, we have something like that coming, but I've been hearing that for more than a year ;) -SteveA destructor should ONLY be used to free up resources other than GC allocated memory. Because of that, it's generally not used. It should be used almost as a "last resort". For example, a class that holds a file descriptor should have both a destructor (which closes the descriptor) and a manual close method. The former is to clean up the file descriptor in case nobody thought to close it manually before all references were gone, and the latter is because file descriptors are not really managed by the GC, and so should be cleaned up when they are no longer used. This kind of gives us a paradox, since the class is managed via the GC, how do you know it's no longer used (that is, how do you know this is the last reference to it)? That is really up to the application design. But I wouldn't recommend relying on the GC to clean up your descriptors. -SteveI've actually run into this very issue: I was iterating on files, opening them, and placing the descriptor in GC-allocated RAII data. I can't remember if class or struct, but not a big issue. Come to think about it, I think I was using "File", but allocating them because I thought they were classes `auto f = new File("my file", "r")`. After running for a second, my program halts, because an exception was thrown trying to open a new file: "Cannot open file: Too many open file handles". It was basically: Sure, the GC will destroy and close files for you... if you forget... eventually... I ended up closing them in scope(exit) blocks. Problem immediately solved. Or I could have stopped allocating my File's on the heap. Either way, it shows you shouldn't rely on the GC for deterministic destruction.
Feb 01 2013
On Friday, 1 February 2013 at 15:37:25 UTC, Steven Schveighoffer wrote:On Fri, 01 Feb 2013 02:07:00 -0500, monarch_dodra <monarchdodra gmail.com> wrote:Oh. Wow. That's news to me. I'd say as long as you don't new your structs, you are fine, but apparently, dynamic arrays don't clean up after themselves either (!) That's a whole other ballgame... That's quite scary. It brings back into question a few of my implementations...On Thursday, 31 January 2013 at 23:53:26 UTC, Steven Schveighoffer wrote:Actually, that's a different problem. File is a struct, and structs do NOT have their destructor run by the GC. Only Objects do. This is a GC limitation, since structs do not contain a pointer to their typeinfo like classes do, and there is no provision for storing a pointer to the typeinfo of a block. It could be fixed by a more precise GC. AIUI, we have something like that coming, but I've been hearing that for more than a year ;) -SteveA destructor should ONLY be used to free up resources other than GC allocated memory. Because of that, it's generally not used. It should be used almost as a "last resort". For example, a class that holds a file descriptor should have both a destructor (which closes the descriptor) and a manual close method. The former is to clean up the file descriptor in case nobody thought to close it manually before all references were gone, and the latter is because file descriptors are not really managed by the GC, and so should be cleaned up when they are no longer used. This kind of gives us a paradox, since the class is managed via the GC, how do you know it's no longer used (that is, how do you know this is the last reference to it)? That is really up to the application design. But I wouldn't recommend relying on the GC to clean up your descriptors. -SteveI've actually run into this very issue: I was iterating on files, opening them, and placing the descriptor in GC-allocated RAII data. I can't remember if class or struct, but not a big issue. Come to think about it, I think I was using "File", but allocating them because I thought they were classes `auto f = new File("my file", "r")`. After running for a second, my program halts, because an exception was thrown trying to open a new file: "Cannot open file: Too many open file handles". It was basically: Sure, the GC will destroy and close files for you... if you forget... eventually... I ended up closing them in scope(exit) blocks. Problem immediately solved. Or I could have stopped allocating my File's on the heap. Either way, it shows you shouldn't rely on the GC for deterministic destruction.
Feb 01 2013
On Fri, 01 Feb 2013 10:46:11 -0500, monarch_dodra <monarchdodra gmail.com> wrote:On Friday, 1 February 2013 at 15:37:25 UTC, Steven Schveighoffer wrote:Dynamic arrays do clean up the array memory. For arrays of objects, or arrays of structs that have only GC-based resources, those items are also individually cleaned up by the GC. But if you had, for instance, an array of self-closing file descriptor structs, those would NOT be cleaned up by the GC.This is a GC limitation, since structs do not contain a pointer to their typeinfo like classes do, and there is no provision for storing a pointer to the typeinfo of a block. It could be fixed by a more precise GC. AIUI, we have something like that coming, but I've been hearing that for more than a year ;) -SteveOh. Wow. That's news to me. I'd say as long as you don't new your structs, you are fine, but apparently, dynamic arrays don't clean up after themselves either (!) That's a whole other ballgame...That's quite scary. It brings back into question a few of my implementations...People should definitely be aware of this limitation. It usually is not of any concern because it is rare to have a struct that has a non-GC reference on the heap. But it is something to be aware of. Note that if your struct is a *member* of a class, it's destructor will be called because it's destructor is called as part of the object's destructor. But this isn't always what you want! I think people have been harping on this limitation of File (and reference-counted structs in general) for a long time. There is a bugzilla issue for it somewhere. -Steve
Feb 01 2013
On 2013-02-01 16:37, Steven Schveighoffer wrote:Actually, that's a different problem. File is a struct, and structs do NOT have their destructor run by the GC. Only Objects do. This is a GC limitation, since structs do not contain a pointer to their typeinfo like classes do, and there is no provision for storing a pointer to the typeinfo of a block. It could be fixed by a more precise GC. AIUI, we have something like that coming, but I've been hearing that for more than a year ;)So currently the only way to make a struct's destructor work when the struct is on the heap is to encapsulate that struct in a class? I have tested the following: struct A { ... } class C { A a; ... } A a = A(); // OK A *b = new A(); // BAD, no finalization C c = new C(); // OK, a's destructor will be called
Feb 01 2013
On Jan 31, 2013, at 11:07 PM, "monarch_dodra" <monarchdodra gmail.com> wrote= :On Thursday, 31 January 2013 at 23:53:26 UTC, Steven Schveighoffer wrote:ated memory. Because of that, it's generally not used.=20 A destructor should ONLY be used to free up resources other than GC alloc=ructor (which closes the descriptor) and a manual close method. The former i= s to clean up the file descriptor in case nobody thought to close it manuall= y before all references were gone, and the latter is because file descriptor= s are not really managed by the GC, and so should be cleaned up when they ar= e no longer used.=20 It should be used almost as a "last resort". =20 For example, a class that holds a file descriptor should have both a dest=ow do you know it's no longer used (that is, how do you know this is the las= t reference to it)? That is really up to the application design. But I wou= ldn't recommend relying on the GC to clean up your descriptors.=20 This kind of gives us a paradox, since the class is managed via the GC, h=hem, and placing the descriptor in GC-allocated RAII data. I can't remember i= f class or struct, but not a big issue. Come to think about it, I think I wa= s using "File", but allocating them because I thought they were classes `aut= o f =3D new File("my file", "r")`.=20 -Steve=20 I've actually run into this very issue: I was iterating on files, opening t==20 After running for a second, my program halts, because an exception was thr=own trying to open a new file:"Cannot open file: Too many open file handles". =20 It was basically: Sure, the GC will destroy and close files for you... if y=ou forget... eventually...=20 I ended up closing them in scope(exit) blocks. Problem immediately solved.=Or I could have stopped allocating my File's on the heap.=20 Either way, it shows you shouldn't rely on the GC for deterministic destru=ction. The GC currently doesn't finalize structs, only classes. So that's an issue a= s well.=20=
Feb 01 2013
On Wed, 30 Jan 2013 03:15:14 -0500, Mike Parker <aldacron gmail.com> wrote:My understanding is that the current implementation only runs collections when memory is allocated. Meaning, when you allocate a new object instance, or cause memory to be allocated via some built-in operations (on arrays, for example), the GC will check if anything needs to be collected and will do it at that time. I don't know if it's run on every allocation, or only when certain criteria or met, and I really don't care. That's an implementation detail. The D language itself does not specify any of that.This isn't quite accurate. The GC first checks to see if there is a free block that would satisfy the allocation, and if it can't find one, THEN it runs a collection cycle, and if then it cannot allocate the block from any memory regained, it then asks for more memory from the OS. This can lead to the collection cycle running quite a bit when allocating lots of data. I don't know if there are any measures to mitigate that, but there probably should be. -Steve
Jan 31 2013
GG.reserve can be handy for this. It tells the GC to pre allocate a block of= memory from the OS.=20 On Jan 31, 2013, at 7:12 AM, "Steven Schveighoffer" <schveiguy yahoo.com> wr= ote:On Wed, 30 Jan 2013 03:15:14 -0500, Mike Parker <aldacron gmail.com> wrote=:=20when memory is allocated. Meaning, when you allocate a new object instance,= or cause memory to be allocated via some built-in operations (on arrays, fo= r example), the GC will check if anything needs to be collected and will do i= t at that time. I don't know if it's run on every allocation, or only when c= ertain criteria or met, and I really don't care. That's an implementation de= tail. The D language itself does not specify any of that.My understanding is that the current implementation only runs collections==20 This isn't quite accurate. =20 The GC first checks to see if there is a free block that would satisfy the=allocation, and if it can't find one, THEN it runs a collection cycle, and i= f then it cannot allocate the block from any memory regained, it then asks f= or more memory from the OS.=20 This can lead to the collection cycle running quite a bit when allocating l=ots of data. I don't know if there are any measures to mitigate that, but t= here probably should be.=20 -Steve
Jan 31 2013