Live data from Hacker News

Reference count, don't garbage collect

kevinlawler.com

391–400 of 415 posts

Re: Reference count, don't garbage collect

#391
post #362
post #341

Earlier quoted context omitted.

> What Apple has is excellent marketing. Whoa! Marketing? Interop with C is a MASSIVE use-case. And iOS is A LOT faster and more responsive than android. That is, right there, total proof that can't denied. I do both, and the speed of apple way and the simplicity of bridge the C-abi is not a joke.

The android/iOS comparison has many more factors than GC type. I suspect the main difference is processor type - Qualcomm ARM has been very disappointing so far, and GC type doesn't even come into it.

Certainly, but Apple code also run on x86.

My main point actually is that Apple don't pick this route for the fun of it. It HAS a need to be performant on mobiles devices (that have less luxury to get a GC that eat Ram) and that need represent A LOT OF MONEY. You can say any step about this, including making processors, are directly or indirectly related to the need.

P.D: I don't see Rc VS Gc as enemies, but as faces of the same coin. ARC is just a way to apply some Gc lessons to naive Rc. I think naive Rc is truly worse than Gc, but smart Rc is total fine and consider it the best of both in the general case...

Re: Reference count, don't garbage collect

#392
post #342
post #329

Earlier quoted context omitted.

> Do you honestly claim that you know when deallocations happen in any codebase full of conditionals depending on outside effects (user input, network, etc)? Yes. C programs have been doing this for over 40 years now. A leak free C program has an equivalent free for every malloc, which means they know exactly when everything gets allocated and freed.

That just means that every allocation has a pair that frees it - that’s different from knowing how many allocations happen, when and when does the corresponding free happen. For a simple example, take a text editor (sure, you would likely allocate a much bigger buffer in practice) that allocates for each line of text an object, and adds the buffer’s pointer to a list to be freed - this freeing happens when the user c…

It's not different though. You asked:

> Do you honestly claim that you know when deallocations happen in any codebase full of conditionals depending on outside effects (user input, network, etc)?

And the answer to that is yes. You even admitted that here:

> While you do know that every allocation will be freed and know their relative order

This is a lot more specific than "the GC will free this memory at some indeterminate point that it deems acceptable".

Additionally, in your specific example:

> this freeing happens when the user closes the open text file window

So you can plan for that. You can pop up a saving screen if you run tests and realize that the deallocations take a bit of time. With GC, it's luck of the draw. I'm speaking from experience.

I wrote a tool that used Roslyn to do some transpiling of a custom format in our company. It was very important that it ran fast, since this algorithm was going to be run in a time sensitive situation. And it had to free it's memory as soon as it was done using it, since it was hot swapping the DLLs and I needed to make sure I wasn't getting name collisions from DLLs that were waiting for the GC to run to fully unload the old DLLs. I tried so many different ways to tell C# GC to collect the object tree that I knew was no longer necessary, but it was seemingly impossible.

Microsoft even has a page dedicated to debugging why an assembly won't unload and it reads:

> The difficult case is when the root is a static variable or a GC handle.[0]

Now you may say that this while problem only arises because of my weird specific use case, which is true but I couldn't change my requirements since those were hard requirements from my company. This could all easily be solved if a GC allowed you to define the concept of ownership. I had references hanging around that didn't matter because the object holding the references didn't own that memory.

All that to say, yes you can know exactly when you're memory will be deallocated in a language like C. In a language like C#, your left to the whims of the GC which can be a deal breaker in lots of cases.

What really gets me too, is languages like C# end up creating DI frameworks with the "novel" concept of lifetime requirements to make sure object lifetimes are properly scoped. What the heck? It's got a GC. Why did they go through all that trouble if the GC just cleans it up for you? If I have to think about object lifetimes, I may as well switch to a language that makes that explicit rather than a language that obfuscated it as much as possible.

[0]: https://docs.microsoft.com/en-us/dotnet/standard/assembly/un...

Re: Reference count, don't garbage collect

#394
post #392
post #342

Earlier quoted context omitted.

That just means that every allocation has a pair that frees it - that’s different from knowing how many allocations happen, when and when does the corresponding free happen. For a simple example, take a text editor (sure, you would likely allocate a much bigger buffer in practice) that allocates for each line of text an object, and adds the buffer’s pointer to a list to be freed - this freeing happens when the user c…

It's not different though. You asked: > Do you honestly claim that you know when deallocations happen in any codebase full of conditionals depending on outside effects (user input, network, etc)? And the answer to that is yes. You even admitted that here: > While you do know that every allocation will be freed and know their relative order This is a lot more specific than "the GC will free this memory at some indeter…

Well, you can always go a layer below and use a bytebuffer (or its C# equivalent). You can drop it at the end of the task in an instant.

But I don’t think that giving up the comfort/performance of a good GC is a good tradeoff in all the other cases. The same way Rust et alia can opt into some form of GC with (A)RC, GC languages can have escape hatches as well.

Re: Reference count, don't garbage collect

#395

Earlier quoted context omitted.

Yep. The language doesnt allow data cycles. Nobody ever complained about that or even noticed it.

That seems a little hard to believe. I can't think of many complex pieces of software I've worked on that didn't have such cycles (e.g. any sort of tree structure where parents need to know about children and children need to know about parents - how does Nim handle that?)

You typically use a weak pointer from child to parent in those situations. So there are no ownership cycles. Languages without garbage collectors (C/C++) pretty much require you to not have ownership cycles or your code will crash during cleanup. Unless you add specific code to detect it and stop it from happening. So I assume you mostly work in GC languages and not C/C++?

Re: Reference count, don't garbage collect

#396

Earlier quoted context omitted.

What happens in your language when a linked list is freed? Doesn't running its destructor (or its equivalent) take a linear amount of time relative to the length of the list?

The compiler uses arrays not linked lists. One of the big mistakes that other functional compilers make (IMHO) is that they use linked lists. It is a huge performance problem. There is a reason why high-performance software written in C++ and C always use arrays and not linked lists. Memory access patterns is the #1 thing to optimise for on modern CPUs.

So, as I understand it, you avoid pauses by avoiding data structures with long chains of pointers. The same will work equally well in a language with a GC. It's also not the case that reference-counting itself doesn't result in pauses itself, but that the user is responsible for using such data structures that they do not result in pauses. Which I think is the only way when you care about performance, no matter whether you use manual memory management, reference counting or a tracing GC, so that's by no means a criticism of you or your language, I think it's very sensible. But I think that describing it as a no-pause memory management mechanism is a mischaracterisation.

Re: Reference count, don't garbage collect

#397

Earlier quoted context omitted.

Serious questions: if these garbage collectors are so good, why aren't they widely used? My guess is that they have downsides such as low throughput, high CPU usage, high memory usage, etc... You can't import a JVM GC into V8, to stay with my example, but you can reimplement the ideas if you have quasi-infinite money like Google.

For ZGC/Shenandoah because they're new, and they're new because they're extremely hard to implement well. For C4 because it is expensive and requires kernel patches. Also there isn't a whole lot of need for them in many use cases. Web servers for example have far bigger latency problems than GC, normally. Pauseless GC was historically driven by the HFT/finance sector for that reason. Also yes, pauseless GC tends to h…

Thank you. I didn't know that one GC that I regularly use (as a user) - the one in Android - is so advanced these days. Interesting!

Re: Reference count, don't garbage collect

#398

This debate has gone round and round for decades. There are no hard lines; this is about performance tradeoffs, and always will be. Perhaps the biggest misconception about reference counting is that people believe it avoids GC pauses. That's not true. Essentially, whereas tracing GC has pauses while tracing live data, reference counting has pauses while tracing garbage. Reference counting is really just another kind…

> reference counting has pauses while tracing garbage.

Which pauses you are meaning?

Reference counting is not free, but there are no long pauses (long compare to GC, e. g. in JVM under certain workloads you can get 100ms pauses).

Re: Reference count, don't garbage collect

#399
post #193
post #92

Earlier quoted context omitted.

> and how much control the programmer has over RC costs (determinism allows to profile this and apply mitigations). I fail to see how would it be deterministic in a highly dynamic program. Like, imagine a game for example where the user can drag'n'drop different things to a "parent" object. Observability is imo an entirely different axis. > RC with borrow checking can avoid a lot of refcount increments. That's the sa…

> Like, imagine a game for example where the user can drag'n'drop different things to a "parent" object. Where is the reference count going to 0 here? Presumably the object you dragged from one parent to another parent just swapped the reference and no ref count ever went to 0 which would have triggered a free. I'm guessing OP meant deterministic as in, "oh when I profile my code and it hits that big lag spike, this…

> I've had so many "fun" times trying to force GC to collect at specific points

Because that's not the type of application for which a non-deterministic GC is suited. The vast majority of applications don't need that determinism. Right tool for the job.

Re: Reference count, don't garbage collect

#400

Earlier quoted context omitted.

> There are zero GC pauses. Unless you claim that a C++ alloc/feee call is “garbage collection”. Alloc/free can introduce arbitrary pauses last I checked, so yes, there are pauses. Any time doing book keeping for resources rather than running your code counts as GC time.

> Any time doing book keeping for resources rather than running your code counts as GC time. Perhaps a nitpick: memory management time , yes, but not GC time . alloc/free is manual memory management, not garbage collection.

If you're using alloc/free in your GC, which is what was being implied, then that counts as GC time.
Post reply on HN