You don't like GC? Do you?

Stanislav Blinov stanislav.blinov at gmail.com
Sat Oct 13 14:29:09 UTC 2018


On Saturday, 13 October 2018 at 13:08:30 UTC, Atila Neves wrote:
> On Friday, 12 October 2018 at 23:24:56 UTC, Stanislav Blinov

>> Funny. Now for real, in a throwaway script, what is there to 
>> gain from a GC? Allocate away and forget about it.
>
> In case you run out of memory, the GC scans. That's the gain.

Correction, in case the GC runs out of memory, it scans.

>>>> In fact, the GC runtime will only detract from performance.
>>> Demonstrably untrue. It puzzles me why this myth persists.
>> Myth, is it now?
> Yes.

Please demonstrate.

>> Unless all you do is allocate memory, which isn't any kind of 
>> useful application, pretty much on each sweep run the GC's 
>> metadata is *cold*.
>
> *If* the GC scans.

"If"? So... ahem... what, exactly, is the point of a GC that 
doesn't scan? What are you even arguing here? That you can 
allocate and never free? You can do that without GC just as well.

>>> There are trade-offs, and one should pick whatever is best 
>>> for the situation at hand.
>>
>> Exactly. Which is *not at all* what the OP is encouraging to 
>> do.
>
> I disagree. What I got from the OP was that for most code, the 
> GC helps. I agree with that sentiment.

Helps write code faster? Yes, I'm sure it does. It also helps 
write slower unsafe code faster, unless you're paying attention, 
which, judging by your comments, you're not and aren't inclined 
to.

>> Alright, from one non-native English speaker to another, well 
>> done, I salute you.
>
> The only way I'd qualify as a non-native English speaker would 
> be to pedantically assert that I can't be due to not having 
> learned it first. In any case, I'd never make fun of somebody's 
> English if they're non-native, and that's most definitely not 
> what I was trying to do here - I assume the words "simple" and 
> "easy" exist in most languages. I was arguing about semantics.

Just FYI, they're the same word in my native language :P

>> To the point: *that* is a myth. The bugs you're referring to 
>> are not *solved* by the GC, they're swept under a rug.
>
> Not in my experience. They've literally disappeared from the 
> code I write.

Right. At the expense of introducing unpredictable behavior in 
your code. Unless you thought about that.

>> Because the bugs themselves are in the heads, stemming from 
>> that proverbial programmer laziness. It's like everyone is 
>> Scarlett O'Hara with a keyboard.

> IMHO, lazy programmers are good programmers.

Yes, but not at the expense of users and other programmers who'd 
use their code.

>> For most applications, you *do* know how much memory you'll 
>> need, either exactly or an estimation.

> I don't, maybe you do. I don't even care unless I have to. See 
> my comment above about being lazy.

Too bad. You really, really should.

>> Well, I guess either of those do take more arguments than a 
>> "new", so yup, you do indeed write "less" code. Only that you 
>> have no clue how much more code is hiding behind that "new",
>
> I have a clue. I could even look at the druntime code if I 
> really cared. But I don't.

You should.

>> how many indirections, DLL calls, syscalls with libc's 
>> wonderful poison that is errno... You don't want to think 
>> about that.
>
> That's right, I don't.

You should. Everybody should.

>> Then two people start using your script. Then ten, a hundred, 
>> a thousand. Then it becomes a part of an OS distribution. And 
>> no one wants to "think about that".
>
> Meh. There are so many executables that are part of 
> distributions that are written in Python, Ruby or JavaScript.

Exactly my point. That's why we *must not* pile more crap on top 
of that. That's why we *must* think about the code we write. Just 
because your neighbour sh*ts in a public square, doesn't mean 
that you must do that too.

>>> For me, the power of tracing GC is that I don't need to think 
>>> about ownership, lifetimes, or manual memory management.
>>
>> Yes you do, don't delude yourself.
>
> No, I don't. I used to in C++, and now I don't.

Yes you do, you say as much below.

>> Pretty much the only way you don't is if you're writing purely 
>> functional code.
>
> I write pure functional code by default. I only use 
> side-effects when I have to and I isolate the code that does.
>
>> But we're talking about D here.
>> Reassigned a reference? You thought about that. If you didn't, 
>> you just wrote a nasty bug. How much more hypocrisy can we 
>> reach here?
>
> I probably didn't write a nasty bug if the pointer that was 
> reassigned was to GC allocated memory. It lives as long as it 
> has to, I don't think about it.

In other words, you knew what you were doing, at which point I'd 
ask, what's the problem with freeing the no-longer-used memory 
there and then? There's nothing to "think" about.

>> "Fun" fact: it's not @safe to "new" anything in D if your 
>> program uses any classes. Thing is, it does unconditionally 
>> thanks to DRuntime.
>
> I hardly ever use classes in D, but I'd like to know more about 
> why it's not @safe.

rikki's example isn't exactly the one I was talking about, so 
here goes:

module mycode;

import std.stdio;

import thirdparty;

void mySuperSafeFunction() @safe {
     auto storage = new int[10^^6];
     // do awesome work with that storage...
}

void main() {
     thirdPartyWork();
     writeln("---");
     mySuperSafeFunction(); // this function can't corrupt memory, 
can it? It's @safe!
     writeln("---");
}

module thirdparty;

@system: // just so we're clear

void thirdPartyWork() {
     auto nasty = new Nasty;
}

private:

void corruptMemory() {
     import std.stdio;
     writeln("I've just corrupted your heap, or maybe your stack, 
mwahahahah");
}

class Nasty {
     ~this() {
         corruptMemory();
     }
}

Thus, even if you wrote an entirely "@safe" library, someone 
using it may encounter a nasty bug. Worse yet, they may not. 
Because whether or not the GC calls finalizers depends on the 
overall state of the program. And certainly, *your* code may 
cause third-party code to UB, and vice versa.
Now, of course things wouldn't be called "Nasty" and 
"corruptMemory". They'll have innocent names, and nothing 
conspicuous at a glance. Because that's just how bugs are. The 
point is, GC can't deliver on the @safe promise, at least in the 
language as it is at the moment.

> I write a destructor once, then I never think about it again. 
> It's a lot different from worrying about closing resources all 
> the time. I don't write `scope(exit)` unless it's only once as 
> well, otherwise I wrap the code in an RAII struct.

Ok, same goes for memory management. What's your point?

>> Why is Socket a class, blown up from a puny 32-bit value to a 
>> bloated who-knows-how-many-bytes monstrosity? Will that socket 
>> close if you rely on the GC? Yes? No? Maybe? Why?
>
> I don't know. I don't think Socket should even have been a 
> class. I assume it was written in the D1 days.

Exactly. But it's in a "standard" library. So if I "don't want to 
think about it" I'll use that, right?

>> Can I deploy the compiler on a remote machine with limited RAM 
>> and expect it to always successfully build my projects and not 
>> run out of memory?
>
> If the compiler had the GC turned on, yes. That's not a point 
> about GC, it's a point about dmd.

The answer is no. At least dmd will happily run out of memory, 
that's just the way it is.
It's a point about programmers not caring about what they're 
doing, whether it's GC or not is irrelevant. Only in this case, 
it's also about programmers advising others to do so.


More information about the Digitalmars-d mailing list