Garbage Collector?

Ben via Digitalmars-d digitalmars-d at puremagic.com
Fri Apr 28 00:35:00 PDT 2017


On Thursday, 27 April 2017 at 22:43:56 UTC, Moritz Maxeiner wrote:
> You replied to the wrong person here, seeing as I did not link 
> to the article you're referring to,

Sorry...

> so I'll reply:
> Expanding the continuous memory region a dynamic array consists 
> of (possibly moving it) once it overflows has absolutely 
> nothing to do with the GC, or even the language, it's how the 
> abstract data type "dynamic array" is defined. D just does this 
> transparently for you by default. If you already know the exact 
> or maximum size, you can allocate *once* (not 6 times) using 
> `new` and `.reserve` respectively *before* entering the loop, 
> like that article explains in depth.

You seem to be missing the fact that i pointed this out. The fact 
that the GC might have done up to 6 collection rounds in that 
loop is "ludicrous".

>
> Um, what? Memory (de)allocation (in C often malloc/free) and 
> object (de)contruction (in C usually functions with some naming 
> conventions like `type_init`/`type_deinit`) are on two entirely 
> different layers! Granted, they are often combined in C to 
> functions with names like `type_new`/`type_free`, but they are 
> conceptually two distinct things. Just to be very clear, here 
> is a primitive diagram of how things work:
> make object O of type T:
> <OS> --(allocate N bytes)--> [memory chunk M] --(call 
> constructor T(args) on M)--> [O]
> dispose of O:
> [O] --(call destructor ~T() on O)--> [memory chunk M] 
> --(deallocate M)--> <OS>
>
> D's garbage collector conceptually changes this to:
> make object O of type T:
> <OS> --(GC allocates)--> [GC memory pool] --(allocate N 
> bytes)--> [memory chunk M] --(call constructor T(args) on M)--> 
> [O]
> dispose of O:
> [O] --(call destructor ~T() on O)--> [memory chunk M] 
> --(deallocate M)--> [GC memory pool] --(GC deallocates)--> <OS>
> with the specific restriction that you have *no* control over 
> 'GC deallocates' and only indirect control over 'GC allocates' 
> (by allocating more memory from the GC than is available its 
> the pool).
>
> Working on the memory chunk layer is memory management.
> Working on the object layer is object lifetime management.
> D offers you both automatic memory management and automatic 
> lifetime management via its GC.
> What you describe is manual object lifetime management (which 
> is what std.conv.emplace and object.destroy exist for) and has 
> no effect on the automatic memory management the GC performs.
> You *can* do manual memory management *on top* of the GC's 
> memory pool (using core.memory.GC.{alloc/free) or the newer, 
> generic Alloactor interface via 
> std.experimental.allocator.gc_allocator.GCAllocator.{allocate/deallocate}), but these operations will (generally) not yield any observable difference from the OS's perspective.
>
>>
>> That is assuming the GC removes the memory reference when you 
>> call it. I remember seeing in some other languages ( C# 
>> possibly? ) that referring a variable to be freed only meant 
>> the GC freed the memory when it felt like it, not the exact 
>> spot when you told it.
>
> Again, you seem to mix object lifetime management and memory 
> management. You cannot tell the GC to free memory back to the 
> operating system (which is what the free syscall does and what 
> you seem to be describing). You can *only* free memory you 
> allocated *from* the GC *back* to the GC. The GC decides when 
> (and if) any memory is ever being freed back to the OS (which 
> is kinda one major point of having a GC in the first place).

I know, i do not express myself very well in English.

> In my experience most people's aversion to GCs can be aptly 
> described by the German proverb "Was der Bauer nicht kennt, das 
> frisst er nicht" (the meaning of which being that most people 
> generally like living in comfort zones and rarely - if ever - 
> dare to leave them of their own free will; that includes 
> developers, sadly).

Unfortunately i do have plenty of experience with GC kicking in 
on the wrong moments ( or not at the right moments, people forget 
that one ).

I am sure that the amount of people who develop in GC languages 
is much bigger these days then manual managed languages ( what is 
more or less a rarity these days among the new languages ). Even 
Rust still has some background management going on ( like the 
byte counter ).

Maybe its my opinion only but a good language will not put 
anything in the way of the developer but will point out mistakes.

The Rust compiler is not a bad example but it can be taken a step 
more. Is it so hard for developers when you declare a variable, 
to later also clean it up???

var x = 1;
// Do work
x.free;

Easy ... Sure, it becomes a little bit more tricky with ownership 
but that is where the compiler can help and simply state: "Hey, 
you forgot this variable, it does not seem to be used beyond this 
point". Just calling the x.free seem to be too much work for 
developers these days.

Up to now i found very few languages that did this correctly. But 
this is a offtopic discussion.


More information about the Digitalmars-d mailing list