News for hackers. Stuff that matters.
Re:Reference count, don't garbage collect by mbrodersen on Friday July 29, 2022 @09:07PM (#32283392)
I am the maintainer of a very high-performance JIT compiler for a Haskell like rules programming language used by large enterprises around the world. It uses reference counting + a global optimisation step to reduce the reference count updates to an absolute minimum. The result is compiled code that runs faster than C++ code carefully hand optimised by C++ experts over a 10 year period. There are zero GC pauses. Unless you claim that a C++ alloc/feee call is “garbage collection”. Which is not common terminology. It also (BTW) scales linearly the more cores you throw at it.
Re:Reference count, don't garbage collect by brabel on Saturday July 30, 2022 @03:56AM (#32285119)
You've gone from claiming reference-counting is faster than tracing GC to claiming it's even faster than hand optimized C++, which is quite honestly unbelievable - whatever the reference counting algorithm is doing can be emulated by the hand-optimised C++ code so that's just literally impossible. But anyway, it's a completely fruitless discussion here unless you provide data that we can look at and scrutinize. OP hasn't provided any. You haven't provided any (and I do believe you may think you're right, but I've been in the position of being very confident of something just to be proven completely wrong by giving all my data to others to scrutinize... it's disheartening but necessary to get to the bottom of what's real). It's like the V language saying it can do memory management magically and it's much faster than Rust or whatever when they don't even have a working system yet.
Re:Reference count, don't garbage collect by fnord123 on Saturday July 30, 2022 @04:28AM (#32285219)
> to claiming it's even faster than hand optimized C++, which is quite honestly unbelievable - whatever the reference counting algorithm is doing can be emulated by the hand-optimised C++ code so that's just literally impossible.

There is nuance here. They claimed that their project is faster than a specific hand optimized project. Not faster than a theoretical peak performance c++ program.

I've run into similar situations where python reimplementation s are faster than java because python is easier to change and fixup algorithms. And %timeit in the ipython shell is way easier than the black magic involved in profiling and benchmarking java.

You also have people on rust subreddit or discourse asking for optimization help when their rust is not as fast as a Go example they wrote. Often you get buffered IO going and it's on par. But to melt faces like ripgrep and friends you often need to drop pretences and work on Vec<u8>s.

Re:Reference count, don't garbage collect by brabel on Saturday July 30, 2022 @04:57AM (#32285344)
> And %timeit in the ipython shell is way easier than the black magic involved in profiling and benchmarking java

Unfair criciticm... first, Java has had a REPL for several years and you can time stuff like in Python as easily... second, profiling tools in Java are some of the best available, and are not blackmagic... quite simple to use, just attach them to the running process and hit "profile".

With that said: yes, I've also seen Java programs that run faster than the Rust or C counterpart. I suspect what OP saw falls into this category: a rare example that you take as a rule (maybe I misinterpreted the claim, I admit, but it does sound OP meant his Haskell program and, I assume, others which you write in the same style, cannot be beaten by the equivalent C++).

Re:Reference count, don't garbage collect by fnord123 on Saturday July 30, 2022 @05:54AM (#32285538)
> Unfair criciticm... first, Java has had a REPL for several years and you can time stuff like in Python as easily... second, profiling tools in Java are some of the best available, and are not blackmagic... quite simple to use, just attach them to the running process and hit "profile".

You're right that the java tooling is powerful. But getting numbers out of the JVM is not the black magic. The dark arts are setting up an experiment, managing the JIT warm-up, and interpreting the results. In my experience it's just hell trying to turn those numbers into a convincing argument that we have confidence in our performance. Concrete example: convincing openjdk11 to use AES instructions Vs conscrypt using AES out of the box with no warm-up...

The whole song and dance means that we just don't take it as a priority because it's a tiring sink of effort. On the other hand %timeit is so easy and remains consistent that you can use it with unit tests and offer algorithm fixes in PRs.

Re:Reference count, don't garbage collect by mbrodersen on Saturday July 30, 2022 @08:57PM (#32292009)
The code is not open source unfortunately so I can’t provide evidence. But I have nothing to sell or promote (unlike the V language guys who has a clear motivation to inflate what they are selling). What the compiler does differently is that it does a whole program optimisation pass where it minimises the code manipulating the reference counters to an absolute minimum. This is something you can’t do in a C++ compiler. Which is one of the reason why the resulting machine code is faster. Also, I am using LLVM as the backend. So I am getting the same low-level optimisations that C++ compilers get. However the most important optimisations are done before lowering the code to LLVM. Function specialisation for example is huge (generating multiple versions of the same function with the arguments unlined and optimised away). I am doing quite a few high level optimisations like that before even lowering it to LLVM.
Re:Reference count, don't garbage collect by staticassertion on Saturday July 30, 2022 @06:10AM (#32285590)
> whatever the reference counting algorithm is doing can be emulated by the hand-optimised C++ code so that's just literally impossible.

shared_ptr and unique_ptr have pretty significant overhead and are common practice, even for optimized codebases, so I wouldn't say it's impossible at all.

Re:Reference count, don't garbage collect by mbrodersen on Saturday July 30, 2022 @09:01PM (#32292045)
You are 100% right. At some point I measured smart_ptr to be 25x slower than raw pointers. The compiler I am maintaining is not using C++ style smart pointers. It is using a global whole program optimisation pass to reduce reference manipulation to a minimum. Basically what a world class C++ programmer with years of experience optimising performance would do. It is just done automatically.
Re:Reference count, don't garbage collect by tpolzer on Saturday July 30, 2022 @05:11PM (#32290378)
unique_ptr is nearly overhead free compared to a bare pointer (except for argument passing... because of ABI concerns).

shared_ptr is expensive and easy to build leaks with, so a lot of code bases avoid it where possible. Though it's only expensive when you copy it, moving it is ~free.

Re:Reference count, don't garbage collect by staticassertion on Saturday July 30, 2022 @05:44PM (#32290658)
This is just a more detailed version of my point lol you just listed the reasons they are not free.
Re:Reference count, don't garbage collect by yakubin on Saturday July 30, 2022 @05:50AM (#32285524)
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?
Re:Reference count, don't garbage collect by mbrodersen on Saturday July 30, 2022 @09:04PM (#32292064)
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.
Re:Reference count, don't garbage collect by yakubin on Sunday July 31, 2022 @06:23AM (#32294595)
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 by mbrodersen on Sunday July 31, 2022 @10:14PM (#32301150)
So according to your logic no pause GC is impossible? In that case my claim is that it works as fast as what an expert in C/C++ optimisations would hand craft the compiled code to do by carefully minimising allocs/frees. This is what AAA games do to minimise stuttering. You can achieve the same with GC languages like Java. However you then have to manually keep a pool of objects and manually “alloc/free” objects from that pool. That is what games written in GC languages do to avoid random GC pauses.
Re:Reference count, don't garbage collect by yakubin on Monday August 01, 2022 @04:47AM (#32303502)
No-pause GC is possible, when we're talking about concurrent GCs, but it also shouldn't be mistaken for a "no-overhead GC". And reference-counting, as long as the actual reference counting isn't done in a separate thread as well, instead of blocking in a destructor, which triggers other destructors, is not a no-pause GC. It's true that application developer can avoid pauses even then, but that's a different claim.

From what I've been told, C++ games do another thing and just use arena allocators, which make allocations cheap (just an integer addition, provided you know a reasonable upper bound on the size of an arena, and if you don't, you may reserve a large piece of virtual memory, and commit it later in reasonably small, but also not too large chunks) and free-s even cheaper (either reset the integer, so that the arena can be reused, or a single syscall to unmap the whole arena in one go). That's a different strategy than making a lot of little allocs and frees, and then trying to minimize them by reusing objects, which is also quite hairy.

Re:Reference count, don't garbage collect by afiori on Saturday July 30, 2022 @06:03AM (#32285565)
My guess is that this could be done concurrently and/or in parallel.

It still take time linear in length, but dead nodes are by definition stable so it does not really matter when you free them.

Re:Reference count, don't garbage collect by yakubin on Saturday July 30, 2022 @06:41AM (#32285719)
So just like with tracing GCs. You do have a pause, which you may avoid with parallelism, or smear out incrementally. If you do it in parallel, your reference counting needs to be atomic, which adds further overhead. You still need to perform all the reference counting operations for each element of the list, not just free them, because part of the list may be shared. E.g. in SML:

  fun replace_head_with_1 (_::xs) = 1::xs;
  val a = [2, 3, 4];
  val b = replace_head_with_1 a;
Now a and b share the tail.

And a linked list is only a simple demonstration of a chain of pointers. It occurs spontaneously outside of containers, when you just write e.g. classes which have objects of other classes as their fields. In Haskell that would be records, or just an algebraic data type. Or just closures.

Re:Reference count, don't garbage collect by pclmulqdq on Friday July 29, 2022 @10:33PM (#32283807)
The global optimization step is often what people commonly refer to as "garbage collection." Putting it inside a framework to RC as few times as possible is pretty cool.

However, I doubt the efficacy of your C++ experts: most of the people I know who write C++ are actually really bad at optimizing code. They mostly use it for legacy reasons. If you get a team of experienced (and expensive) systems programmers, you will likely get a slightly better result than your GC algorithm.

Re:Reference count, don't garbage collect by mbrodersen on Saturday July 30, 2022 @09:09PM (#32292113)
The C++ code I am referring to was hand optimised and maintained for 10+ years before the compiler I am maintaining was fast enough to take over. I never looked at the C++ code myself. I simply use it as the milestone to beat. When I took over the maintenance of the compiler it was 25x slower than the C++ code. It took a lot of work to finally make it faster. I also used the C++ code to compare the output of the compiler and the C++ code. I found quite a few bugs in the C++ code doing that by the way.
Re:Reference count, don't garbage collect by UncleEntity on Saturday July 30, 2022 @04:49AM (#32285299)
> However, I doubt the efficacy of your C++ experts: most of the people I know who write C++ are actually really bad at optimizing code.

Which is a very good reason to develop an optimized GC algorithm, the domain experts can crank out code without having to optimize every single memory (de)allocation which sounds like a waste of their time.

It’s funny, people don’t usually doubt that a modern compiler can do a better optimization job than an expert but add a memory management algorithm and that’s a bridge too far.

Re:Reference count, don't garbage collect by mbrodersen on Saturday July 30, 2022 @10:17PM (#32292541)
Yep you are absolutely right. The business rules domain experts using the language are way more productive using a pure functional language that takes care of all the nitty gritty performance and memory issues for them. The code they write is 100% focused on solving customer problems.
Re:Reference count, don't garbage collect by pclmulqdq on Sunday July 31, 2022 @07:06PM (#32299732)
Personally, I think non-GC languages are very much overused. If you are writing business logic, and not counting cycles (even worse - if you are never planning to count cycles), you should probably not use C++ or Rust.

However, a GC is a lot slower than manual memory management, which contrasts with the fact that most compiler activities are actually pretty low in overhead (now - it didn't used to be this way). Really, the only cost overhead left is the abstraction mismatch, and that is not too bad, when you compare to how bad humans are at writing assembly.

That said, this case looks like one where the C++ experts spent very little time optimizing (mostly writing business logic), and probably made a very poor choice of tools.

Re:Reference count, don't garbage collect by aidenn0 on Monday August 01, 2022 @10:35AM (#32306548)
> However, a GC is a lot slower than manual memory management, which contrasts with the fact that most compiler activities are actually pretty low in overhead (now - it didn't used to be this way). Really, the only cost overhead left is the abstraction mismatch, and that is not too bad, when you compare to how bad humans are at writing assembly.

There is a triangle of GC performance; througput, latency (i.e. pause length), and memory overhead. Manual memory management will often be slower (in the throughput sense) than a throughput-tuned GC because:

1. Manual memory management typically precludes moving live data

2. Manual memory management often frees data as soon as it is dead

GC will often have faster allocations than manual memory management because #1 makes it possible to just use a pointer-increment for allocation. GC will often have faster freeing of data because of #2; in particular using a nursery with Cheney's algorithm makes it O(1) to free an arbitrary amount of data.

Where a throughput optimized GC falls down is in that any code that allocates may have an unpredictable amount of delay.

Also note that for video games, both typical GC and malloc/free are often too slow for per-frame data, so arena allocators are used, which sidestep #2, and allow a pointer-increment allocation without needing #1. This is specifically because there are a lot of objects with exactly the same bounds on their lifetime. Special-purpose algorithms will almost always trump general-purpose algorithms when run on the workload they are optimized for.

Re:Reference count, don't garbage collect by dataflow on Saturday July 30, 2022 @04:48AM (#32285295)
What I understood from their comment (which may not be correct) is the following. Say you have something like this:

  extern void foo(T *p);   // some arbitrary function
  
  void bar1(bool cond)
  {
    ..
    auto p = std::make_unique<T, your_deleter>();
    if (cond) { return foo(p.release()); }
    ...
  }
This requires the compiler to call your_deleter::operator() regardless of whether cond is true or false, even though it's unnecessary (and can thus be slower) in the case where cond is true. Moreover, the obvious way to avoid it is to write it "C-style":

  void bar2(bool cond)
  {
    ..
    auto p = new T();
    if (cond) { return foo(p); }
    ...
    your_deleter()(p);
  }
which can up being faster when cond is true. But this isn't something an expert would generally want to do, as now the C++ code becomes unidiomatic, fragile, and unmaintainable.

In an ideal world, though, you could have an optimizer smart enough to do that transformation automatically. C++ compilers already do that in trivial cases, but they can't do it in general. My impression is that their Haskell compiler exploits the internal knowledge of what your_deleter does (i.e. reference counting) in order to optimize the code in various ways, like optimizing out such code, consolidating refcount updates, etc. And if I understand this correctly, there's no surprise at all that it can be faster than idiomatic C++ code written even by experts.

The question for me isn't the expertise of their programmers. Perhaps in their case they genuinely do need to have lots of objects on the heap, have (say) tight loops where they (for whatever reason) nevertheless cannot avoid the heap allocations, and don't have much of a use for finalizers besides freeing memory. In which case, I'm not surprised their solution clearly delivers better results than the C++ equivalent. The question from me, instead, is how well they think that generalizes, such as to (a) well-written Haskell programs in general, (b) well-written C++ programs in general, and/or (c) other domains. It would be one thing if their solution delivers better results in Haskell than C++ for their use case; it would be another thing if they could claim their solution delivers better results in Haskell than C++ for most use cases.

Re:Reference count, don't garbage collect by mbrodersen on Saturday July 30, 2022 @09:13PM (#32292143)
Yep you are quite right. The optimiser basically does what an experienced C++ optimisation experts would (tediously) do by hand: it carefully reduces the number of reference counter modifications to an absolute minimum by symbolically evaluating the full executing flow of the code. It is something that is doable in a pure functional language like this one. I am not sure if it is possible to do the same in C++ (because of the aliasing rules).
Re:Reference count, don't garbage collect by aaaaaaaaaaab on Saturday July 30, 2022 @05:24AM (#32285434)
std::unique_ptr::release() resets the ptr to nullptr, which will be the first thing the deleter will check for and bail out.

This is a non-issue.

Re:Reference count, don't garbage collect by dataflow on Saturday July 30, 2022 @05:26AM (#32285440)
> which will be the first thing the deleter will check for and bail out.

The point is that check itself is an extra instruction (or two, rather) that would otherwise be skipped entirely.

I'm not saying this commonly makes a difference. I'm just saying this might be something that does make a difference for them in their particular use case.

Also note that I was trying to describe the general phenomenon with a simple example, but this obviously isn't limited to std::unique_ptr.

Re:Reference count, don't garbage collect by mbrodersen on Saturday July 30, 2022 @09:34PM (#32292292)
Just to clarify: it is not a framework. It is a whole program optimisation pass done by the compiler before lowering the intermediate code to LLVM and then generating machine code.
Re:Reference count, don't garbage collect by viraptor on Friday July 29, 2022 @10:10PM (#32283689)
How do you collect cycles without a pause?
Re:Reference count, don't garbage collect by eru on Friday July 29, 2022 @10:22PM (#32283743)
There are solutions to this one. Real time garbage collectors are a thing. You just might not be able to collect the cycle in one GC run.

Or you can do what Erlang does: Erlang has neither mutation nor laziness, so you can't create cycles. The GC also lays out object in topological order in memory, so that you can detect garbage without tracing every life object.

Re:Reference count, don't garbage collect by viraptor on Saturday July 30, 2022 @12:01AM (#32284176)
The comment claimed "There are zero GC pauses." Tbh, it's not clear how to interpret that. But real time simply means the pauses are guaranteed not to cross the realtime response budget. You still need to schedule the collection while the mutator is paused.
Re:Reference count, don't garbage collect by omginternets on Friday July 29, 2022 @11:52PM (#32284134)
Where can I read about Erlang’s magic?
Re:Reference count, don't garbage collect by eru on Saturday July 30, 2022 @12:10AM (#32284211)
Re:Reference count, don't garbage collect by elcritch on Saturday July 30, 2022 @02:09AM (#32284681)
By requiring non-cyclic data structures or provide "weak" references. It's actually pretty easy to write most code without cycles. I program a lot in Nim and generally compile lots of programs with ARC and no cycle collector without issue.
Re:Reference count, don't garbage collect by mbrodersen on Saturday July 30, 2022 @10:18PM (#32292547)
Yep. The language doesnt allow data cycles. Nobody ever complained about that or even noticed it.
Re:Reference count, don't garbage collect by wizofaus on Saturday July 30, 2022 @10:30PM (#32292606)
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?)
Re:Reference count, don't garbage collect by elcritch on Sunday July 31, 2022 @04:36PM (#32298600)
Nim does allow cycles and the new GC is non-atomic RC + cycle collector.

Though I’ve been hacking on a UI framework written in Nim. Its ui nodes form a tree structure that only tracks parent => child. When it needs the parent info it makes a stack of parents during processing.

Essentially it moves the cycle collector / GC work to extra work during processing. But it’s cheaper since you’re already accessing the memory.

Re:Reference count, don't garbage collect by mbrodersen on Sunday July 31, 2022 @05:55AM (#32294489)
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 by wizofaus on Sunday July 31, 2022 @04:05PM (#32298320)
We were talking about Nim, which is language I know next to nothing about (but very familiar with C/C++, Swift - which has weak pointers, as well as GC languages like JavaScript/Java/C# etc.)
Re:Reference count, don't garbage collect by elcritch on Sunday July 31, 2022 @04:04PM (#32298308)
Not sure what you mean but Nim allows data cycles.

I just prefer to write cycle free code when I can and turn off the cycle collector. Though Nim’s cycle collector performs well and does some tricks using the RCs.

Re:Reference count, don't garbage collect by mbrodersen on Saturday July 30, 2022 @09:17PM (#32292168)
The language has zero data cycles by design. It turns out that we didn’t need it. Thinking about it, I can’t remember even a single situation in my 30+ years career where I needed a data structure with data cycles. There are usually better ways to do it in my experience.
Re:Reference count, don't garbage collect by pkolaczk on Saturday July 30, 2022 @04:07AM (#32285157)
I simply don't do cycles. Software is simpler without them.
Re:Reference count, don't garbage collect by mbrodersen on Saturday July 30, 2022 @09:36PM (#32292306)
Agree. I can’t even come up with an example that couldn’t be done better without them.
Re:Reference count, don't garbage collect by dataflow on Friday July 29, 2022 @11:31PM (#32284050)
I'm gonna take a guess they dedicate a core to GC (or something along these lines).
Re:Reference count, don't garbage collect by mbrodersen on Saturday July 30, 2022 @09:20PM (#32292190)
No each thread does it’s own alloc/free. I reduce the locking to a minimum by using per-thread caching and memorisation. I had to implement that to make the code scale linearly with number of cores. Without per-thread caching it would only scale to about 3 cores. Now it scales very cleanly. Which is nice.
Re:Reference count, don't garbage collect by viraptor on Friday July 29, 2022 @11:57PM (#32284156)
That's not enough. Imagine a circular linked list. GC looks at an outside pointer to item A in it. Now another thread removes A from the list and moves the outside pointer to the next item. After that, GC would see all items in the list not referenced by anything (apart from the cycle).
Re:Reference count, don't garbage collect by dataflow on Friday July 29, 2022 @11:59PM (#32284173)
Yeah, I didn't say it was sufficient. I just said it's probably one of the things they do.
Re:Reference count, don't garbage collect by tsimionescu on Saturday July 30, 2022 @02:17AM (#32284708)
free() calls that have to run for a data-dependent amount of time are more or less equivalent to GC pauses (assuming a concurrent GC that doesn't need to stop the world, like Java's). The most typical example is free()-ing a a linked list, which takes O(n) free() calls to free with a simple RC mechanism.
Re:Reference count, don't garbage collect by kccqzy on Saturday July 30, 2022 @02:28AM (#32284764)
If you are assuming GC does not need to stop the world, you can also assume that the freeing of memory (including the O(n) calls to free()) will not be done in a critical path; all memory could be handed off to a separate dedicated thread that actually calls free(). Or in a RPC or HTTP server all memory can be freed after the request has been served.

It's very easy to make a reference counting scheme not stop the world. It's a bit more difficult to make a GC implementation so.

Re:Reference count, don't garbage collect by altfredd on Saturday July 30, 2022 @03:11AM (#32284949)
> all memory could be handed off to a separate dedicated thread that actually calls free()

That only works when you have infinite memory (or infinite CPU resources).

> It's very easy to make a reference counting scheme not stop the world. It's a bit more difficult to make a GC implementation so.

Only if by "not stopping the world" you mean your previous suggestion (leaking unbounded amount of memory to free() everything at some later point). When your memory is bounded, you will eventually have to stop/crash once you have run out of it.

AFAIK, the best modern state of art garbage collectors have stop-the-world pauses, proportional to size of root set and/or thread count. I'd love to see an RC implementation, that does not have stop-the-world pauses at all, but that sounds as audacious as claims of perpetual motion machine.

Re:Reference count, don't garbage collect by andreareina on Saturday July 30, 2022 @06:00AM (#32285556)
I don't think the gp is describing the null garbage collector, rather one that can work incrementally and concurrently with the program doing its thing. Whereas a concurrent tracing gc has the problem of data changing while it runs and so special care has to be taken not to corrupt memory.
Re:Reference count, don't garbage collect by kccqzy on Wednesday August 03, 2022 @08:31PM (#32338012)
I don't think you understood my point. So let me give you a more concrete example.

The Linux kernel uses RCU to manage data structures that are concurrently read and updated. When an old value (after an update) is no longer needed, a thread can either:

(a) block for a while to make sure no other thread is using it using synchronize_rcu() and then free the memory (see https://www.kernel.org/doc/html/latest/core-api/kernel-api.h...)

(b) if the thread cannot block, it will use call_rcu to register a callback to free the memory at a later time (https://www.kernel.org/doc/html/latest/core-api/kernel-api.h...). That callback generally runs in some other thread to do the cleanup.

Now, moving the concepts to user space, a typical user space implementation will just launch a dedicated thread to free all memory that is no longer needed by any RCU data structures.

Re:Reference count, don't garbage collect by Starlevel001 on Saturday July 30, 2022 @03:53AM (#32285102)
> all memory could be handed off to a separate dedicated thread that actually calls free().

You could go a bit further and have multiple concurrent threads mark the references, then sweep them up in a separate thread, too. Some sort of concurrent sweep and mark reference count system.

Re:Reference count, don't garbage collect by catlifeonmars on Saturday July 30, 2022 @06:54AM (#32285780)
With concurrency you need atomics or locks to synchronize reference counts between cores, unless you can somehow guarantee that ref counts only decrement and can never increment.
Re:Reference count, don't garbage collect by mbrodersen on Saturday July 30, 2022 @09:42PM (#32292332)
The compiler uses arrays for lists instead of linked lists. It is a performance improvement compared with how functional compilers usually do it. And the language is designed in such a way that rule writers manipulate whole lists at a time instead of one element at a time. A bit like array languages. It changes how the code is written compared with traditional functional code.
Re:Reference count, don't garbage collect by naasking on Saturday July 30, 2022 @04:50AM (#32285306)
> 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.

Re:Reference count, don't garbage collect by MaxBarraclough on Saturday July 30, 2022 @05:15AM (#32285402)
> 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.

Re:Reference count, don't garbage collect by naasking on Sunday July 31, 2022 @03:16PM (#32297960)
If you're using alloc/free in your GC, which is what was being implied, then that counts as GC time.
Re:Reference count, don't garbage collect by aaaaaaaaaaab on Saturday July 30, 2022 @05:19AM (#32285413)
On any OS which is not hard realtime, there could be arbitrary pauses with any syscall. This is just nitpicking.
Re:Reference count, don't garbage collect by dento on Saturday July 30, 2022 @05:57AM (#32285544)
Nitpicking: arbitrary pauses can occur even without syscalls, when the OS preempts the program.

More nitpicking: on x86-64, SMI interrupts can cause arbitrary pauses even without any software control involved. Hard realtime on x86-64 is not possible.

Re:Reference count, don't garbage collect by staticassertion on Saturday July 30, 2022 @06:14AM (#32285605)
More nitpicking: Your computer might turn off, cosmic rays might blow fuck up your RAM/CPU, Capital G God could reach down and pause the system, there's a universal quantum pause every 5.391247 × 10^-44 so that the universe can reboot, etc etc etc

Orrrrr, GC pause just means pauses caused by the GC as part of its implementation's work to manage memory.

Re:Reference count, don't garbage collect by naasking on Sunday July 31, 2022 @03:19PM (#32297987)
This is not nitpicking. The OP was implying they were using alloc/free in their GC. Those calls can be doing all sorts of book keeping behind the scenes, including cascading destructor calls which could free a chain of objects the size of live memory. Suffice it to say, that would pause.
Re:Reference count, don't garbage collect by refulgentis on Friday July 29, 2022 @09:37PM (#32283570)
I'm not sure whats being asserted here, could you explain more? This sounds like you're describing a non-stopping GC, and its well understood reference counting is garbage collection. I'm not sure how the rest applies, you're correct, it is possible to write software with just malloc and free.
Re:Reference count, don't garbage collect by cakoose on Friday July 29, 2022 @10:07PM (#32283677)
Re: "it's well understood reference counting is garbage collection". I think this might just be a terminology thing.

There appear to be two ways the terms are categorized:

1. "reference counting" and "garbage collection" are two types of automatic memory management/reclamation.

2. "reference counting" and "tracing garbage collection" are two types of garbage collection.

I think mbrodersen is using #1.

(Back in the 90s and 2000s I feel like #1 was much more prevalent. But #2 seems to have gained popularity since then. My theory is that whoever started writing the Wikipedia content for this stuff picked #2.)

Re:Reference count, don't garbage collect by bjourne on Saturday July 30, 2022 @04:50AM (#32285309)
I think it's more of an industry vs. academia kind of thing. In the mid-90's before Java was released automatic memory management was mostly unknown to the unwashed masses. So garbage collection became synonymous to whatever Java was doing. However, The Garbage Collection Handbook originally published in 1996 defines garbage collection as: "All garbage collection schemes are based on one of four fundamental approaches; mark-sweep collection, copying collection, mark-compact collection or reference counting." So that's an example of terminology #2.
Re:Reference count, don't garbage collect by tsimionescu on Saturday July 30, 2022 @02:22AM (#32284738)
I think this is actually common in the literature, it has nothing to do with Wikipedia. Consider that Python is commonly described as a GC language, though it has always mostly relied on automatic reference counting to free objects (it does have a tracing GC as well to handle cycles, but I'm not sure if it always did).
Re:Reference count, don't garbage collect by int_19h on Saturday July 30, 2022 @02:54AM (#32284886)
I would argue that what matters is the observable behavior. In Python, regardless of how the actual cleanup is distributed between ARC and GC, the behavior that programmer sees is that all unused memory gets cleaned up eventually. So, it makes sense to group it with languages that provide the same guarantee.
Re:Reference count, don't garbage collect by mbrodersen on Saturday July 30, 2022 @09:46PM (#32292360)
Yep. The compiler generates code that works the same way that an experienced C programmer would hand optimise alloc/free calls and manually keep track of shared data by increasing/reducing a reference counter. There is no separate mark/sweep or whatever step.
Re:Reference count, don't garbage collect by rowanG077 on Friday July 29, 2022 @11:00PM (#32283923)
I never understand why people refer to reference counting as garbage collection. It waters down the term so much it becomes essentially useless. Because under that assumptions basically every language has garbage collection in some shape or form.
Re:Reference count, don't garbage collect by pjmlp on Saturday July 30, 2022 @03:41AM (#32285056)
Because we have studied the literature instead of what a random dude in tells at a coffee

https://gchandbook.org/

https://www.sigplan.org/

https://ieeexplore.ieee.org/Xplore/home.jsp

Re:Reference count, don't garbage collect by rowanG077 on Saturday July 30, 2022 @07:09AM (#32285872)
Nice appeal to authority instead of trying to engage in a meaningful way.
Re:Reference count, don't garbage collect by pjmlp on Saturday July 30, 2022 @11:11AM (#32287389)
When one is open to learning, the best path to enlightenment is to use the same books as the Wizards on the tower of knowledge.
Re:Reference count, don't garbage collect by jstanley on Saturday July 30, 2022 @01:19AM (#32284460)
C doesn't have garbage collection.

Furthermore, pretty much every language has I/O, but that doesn't make the term useless.

Re:Reference count, don't garbage collect by tsimionescu on Saturday July 30, 2022 @02:25AM (#32284750)
They do it because they serve the same purpose, though with different trade-offs.

Note that this mostly reflects automatic reference counting, like you have in Python or Swift, not so much manual reference counting like std::shared_ptr or Rc.

Re:Reference count, don't garbage collect by Bolkan on Saturday July 30, 2022 @02:43AM (#32284846)
Pics or gtfo.
Re:Reference count, don't garbage collect by bitcharmer on Saturday July 30, 2022 @04:12AM (#32285175)
Yeah, GP's claim is completely bonkers. And they haven't provided any links or data to back up their nonsensical claim.
Re:Reference count, don't garbage collect by mbrodersen on Saturday July 30, 2022 @09:24PM (#32292229)
Yep the code is not open source so I can’t provide that. However I am happy to explain exactly how it works down to the lowest level details. Perhaps somebody gets inspired to implement it themselves as open source? That would be neat.