www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - A thought about garbage collection

reply Benjamin Thaut <code benjamin-thaut.de> writes:
An article I just read. It even mentions D:

http://sebastiansylvan.wordpress.com/2012/12/01/garbage-collection-thoughts/

I my opinion he especially has a point with the "each object consists 
mostly out of pointers" argument.

Kind Regards
Benjamin Thaut
Dec 19 2012
next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Benjamin Thaut:

 http://sebastiansylvan.wordpress.com/2012/12/01/garbage-collection-thoughts/

It seems a nice blog post. I don't remember what D does regarding per-thread heaps. Maybe Phobos emplace() is not enough and a bigger/better gun is needed to safely allocate in-place a higher percentage of class instances. Bye, bearophile
Dec 19 2012
prev sibling next sibling parent "Robert Jacques" <rjacque2 live.johnshopkins.edu> writes:
On Wed, 19 Dec 2012 16:58:59 -0600, bearophile <bearophileHUGS lycos.com>  
wrote:

 Benjamin Thaut:

 http://sebastiansylvan.wordpress.com/2012/12/01/garbage-collection-thoughts/

It seems a nice blog post. I don't remember what D does regarding per-thread heaps.

It's been proposed and (sadly) rejected.
 Maybe Phobos emplace() is not enough and a bigger/better gun is needed  
 to safely allocate in-place a higher percentage of class instances.

It would be fairly easy to build a library function(i.e. Scope!T or InPlace!T) that uses emplace to store a class inside of a wrapper struct.
Dec 19 2012
prev sibling next sibling parent "jerro" <a a.com> writes:
 It would be fairly easy to build a library function(i.e. 
 Scope!T or InPlace!T) that uses emplace to store a class inside 
 of a wrapper struct.

There already is such function, std.typecons.scoped.
Dec 19 2012
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
jerro:

 There already is such function, std.typecons.scoped.

In your D code what's the percentage of class instantiations done with scoped()? Bye, bearophile
Dec 19 2012
prev sibling next sibling parent "jerro" <a a.com> writes:
 In your D code what's the percentage of class instantiations 
 done with scoped()?

 Bye,
 bearophile

I don't think I've ever actually used it (other than just trying it). When I use classes, I usually want them to be heap allocated. But if you need a class instance on the stack, scoped() looks useful. Are there some issues with it that I'm not aware of?
Dec 19 2012
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Thursday, 20 December 2012 at 00:56:30 UTC, jerro wrote:
 In your D code what's the percentage of class instantiations 
 done with scoped()?

 Bye,
 bearophile

I don't think I've ever actually used it (other than just trying it). When I use classes, I usually want them to be heap allocated. But if you need a class instance on the stack, scoped() looks useful. Are there some issues with it that I'm not aware of?

It is unsafe :D But otherwise works properly. LDC also plan to provide a pass that remove many allocation when it can prove that thing don't escape scope. I don't know if that went into the lastest version, last time I heard of it it was experimental.
Dec 19 2012
prev sibling next sibling parent "David Nadlinger" <see klickverbot.at> writes:
On Thursday, 20 December 2012 at 01:15:51 UTC, deadalnix wrote:
 LDC also plan to provide a pass that remove many allocation 
 when it can prove that thing don't escape scope.

Unfortunately, »many« is not quite true, as escape analysis is hard (and we e.g. currently don't lower D 'scope' on parameters to LLVM's equivalent) – »some« would be better.
 I don't know if that went into the lastest version, last time I 
 heard of it it was experimental.

It's quite an old pass, but has been disabled for a long time. I recently resurrected it, but unfortunately it triggers an unrelated miscompilation, so I couldn't merge it into Git master (and the release) yet: https://github.com/ldc-developers/ldc/pull/206 David
Dec 19 2012
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
jerro:

 I don't think I've ever actually used it (other than just 
 trying it). When I use classes, I usually want them to be heap 
 allocated.


I think to make a difference for the GC (and to improve locality for the cache, and reduce the fan out discussed in the blog post), a good percentage (50%? 70%?) of the class instances need to be allocated in-place. I say "in-place", because a fixed-sized array is allocated in place inside a class instance, even if the instance is allocated on the heap. ------------------------ deadalnix:
 It is unsafe :D But otherwise works properly.

In this thread there are some notes: http://d.puremagic.com/issues/show_bug.cgi?id=5115 Maybe some language support is needed to improve the situation. And this stuff can't want D3. Taking a good look at the design of Rust language is an option.
 LDC also plan to provide a pass that remove many allocation 
 when it can prove that thing don't escape scope. I don't know 
 if that went into the lastest version, last time I heard of it 
 it was experimental.

Escape analysis helps, but it's not a good enough solution. This is said in that blog post too. Bye, bearophile
Dec 19 2012
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Wednesday, 19 December 2012 at 20:47:39 UTC, Benjamin Thaut 
wrote:
 An article I just read. It even mentions D:

 http://sebastiansylvan.wordpress.com/2012/12/01/garbage-collection-thoughts/

 I my opinion he especially has a point with the "each object 
 consists mostly out of pointers" argument.

He neglect to consider immutability (or maybe wasn't aware of) and how, combined with GC it allow some idioms that are very fast. Very good article overall. D's GC should really be aware of TL and immutability of what it does allocate.
Dec 19 2012
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Thursday, December 20, 2012 02:37:16 deadalnix wrote:
 D's GC should really be aware of TL and immutability of what it
 does allocate.

The problem is casting. It's not uncommon to create something as mutable and then cast it to immutable when done. It's stuff like that screws with being able to per-thread GCs. Which thread owns what isn't always clear. - Jonathan M Davis
Dec 19 2012
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Thursday, 20 December 2012 at 01:54:42 UTC, Jonathan M Davis 
wrote:
 On Thursday, December 20, 2012 02:37:16 deadalnix wrote:
 D's GC should really be aware of TL and immutability of what it
 does allocate.

The problem is casting. It's not uncommon to create something as mutable and then cast it to immutable when done. It's stuff like that screws with being able to per-thread GCs. Which thread owns what isn't always clear.

This is where the concept of island make sense, but this is unreasonable to introduce that in D in any short term. However, this kind of cast is explicitly specified as unsafe, and can have unexpected consequences, even in today's code. Obviously if the GC start to play with that, consequences will never be the same !!! (and by that I mean the consequences of a misuse can be way more dramatic)
Dec 19 2012
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Jonathan M Davis:

 The problem is casting. It's not uncommon to create something 
 as mutable and
 then cast it to immutable when done. It's stuff like that 
 screws with being
 able to per-thread GCs. Which thread owns what isn't always 
 clear.

I nearly never cast mutables to immutable. The purpose of casts is to subvert the type system. If you accept that some type system assumption doesn't hold just because casts exist, then you are doomed to ignore every kind of type system assumption, like immutability, safety, purity, nothrowness, and so on. And this is so wrong. So I can't accept your justification that the existence casts disallow per-thread GCs. Do not use cast that way, and give us a "better" GC. Bye, bearophile
Dec 19 2012
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Thursday, December 20, 2012 03:19:17 bearophile wrote:
 Jonathan M Davis:
 The problem is casting. It's not uncommon to create something
 as mutable and
 then cast it to immutable when done. It's stuff like that
 screws with being
 able to per-thread GCs. Which thread owns what isn't always
 clear.

I nearly never cast mutables to immutable. The purpose of casts is to subvert the type system. If you accept that some type system assumption doesn't hold just because casts exist, then you are doomed to ignore every kind of type system assumption, like immutability, safety, purity, nothrowness, and so on. And this is so wrong. So I can't accept your justification that the existence casts disallow per-thread GCs. Do not use cast that way, and give us a "better" GC.

It's perfectly legal to cast from mutable to immutable. You just have to make sure that you don't have any other references to that data. In many cases, it's the only way to get an immutable version of an object (e.g. if you wanted an immutable AA). There's even a helper function for this in the standard library: std.exception.assumeUnique. There's no way that this is going away, and the GC is going to have to take that into account with however it works. It may still be possible to have a per-thread GC, but it definitely complicates things. Casting to and from shared has similar issues and happens for similar reasons. And such casts are essentially forced by std.concurrency. So, you're overly optimistic if you think that the GC can ignore such casts. It must take them into account in whatever it does. - Jonathan M Davis
Dec 19 2012
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Thursday, 20 December 2012 at 02:29:09 UTC, Jonathan M Davis 
wrote:
 On Thursday, December 20, 2012 03:19:17 bearophile wrote:
 Jonathan M Davis:
 The problem is casting. It's not uncommon to create something
 as mutable and
 then cast it to immutable when done. It's stuff like that
 screws with being
 able to per-thread GCs. Which thread owns what isn't always
 clear.

I nearly never cast mutables to immutable. The purpose of casts is to subvert the type system. If you accept that some type system assumption doesn't hold just because casts exist, then you are doomed to ignore every kind of type system assumption, like immutability, safety, purity, nothrowness, and so on. And this is so wrong. So I can't accept your justification that the existence casts disallow per-thread GCs. Do not use cast that way, and give us a "better" GC.

It's perfectly legal to cast from mutable to immutable. You just have to make sure that you don't have any other references to that data. In many cases, it's the only way to get an immutable version of an object (e.g. if you wanted an immutable AA). There's even a helper function for this in the standard library: std.exception.assumeUnique. There's no way that this is going away, and the GC is going to have to take that into account with however it works. It may still be possible to have a per-thread GC, but it definitely complicates things. Casting to and from shared has similar issues and happens for similar reasons. And such casts are essentially forced by std.concurrency. So, you're overly optimistic if you think that the GC can ignore such casts. It must take them into account in whatever it does.

I think the right way to do that is to actually clone the object. You can argue that is a performance cost, but considering the implication on the GC, I'm pretty sure it is a win. Another way to do it safely is to use pure function, but it require that notion of isolated island, and as much as I love the idea, I won't be in favor of introducing it right now into D.
Dec 19 2012
prev sibling parent "SomeDude" <lovelydear mailmetrash.com> writes:
On Wednesday, 19 December 2012 at 20:47:39 UTC, Benjamin Thaut 
wrote:
 An article I just read. It even mentions D:

 http://sebastiansylvan.wordpress.com/2012/12/01/garbage-collection-thoughts/

 I my opinion he especially has a point with the "each object 
 consists mostly out of pointers" argument.

 Kind Regards
 Benjamin Thaut

Another page of interest: http://wiki.luajit.org/New-Garbage-Collector
Dec 19 2012