Live data from Hacker News

For Better Computing, Liberate CPUs from Garbage Collection

spectrum.ieee.org

121–130 of 460 posts

Re: For Better Computing, Liberate CPUs from Garbage Collection

#121
post #3

I’m probably wrong, but didn’t the Symbolics LISP machines have some kind of hardware support for GC? I think for platforms like Android this makes a lot of sense. Should help quite a bit with battery consumption and responsiveness. Also makes sense for server loads in Java or Go.

Symbolics (and other systems like it) had typed memory with hw type checking (so you had safe memory by default), and had one important bit for efficient GC (one that is also utilized by Azul and Shenandoah) - forwarding pointers, in their case implemented "transparently" to actual code.

With forwarding pointer, you can copy data and update a reference in a way that is transparent to concurrently running code, as when it access the data again the CPU (or software implementation) will notice the data had been moved and follow the forwarding pointer to new location.

The rest of the support for GC was centered around structure of virtual memory, without anything very specific to GC in hw - we're talking about things like "memory is divided into X areas, inside each area the lower side is ephemeral... " etc. There was also some register use to keep track of GC status. I think some versions had MMU or page fault handler update the GC register data.

Re: For Better Computing, Liberate CPUs from Garbage Collection

#122

Earlier quoted context omitted.

Oh to be clear I don't have an answer for this off-hand, I'm not that smart. However, if we'd given the 30 years of people developing faster for-loops the task of figuring out how to manage memory statically, I'd wager we'd not be having this conversation right now. It is by no means an easy problem, however.

I think there are essentially two ways of making the compiler statically aware of lifetimes: you can annotate the program with lifetimes, as in Rust, or you can have the compiler infer all of the lifetime information somehow. Adding annotations requires more programmer effort and reduces the level of abstraction of your programming language. Rust takes this approach, but tries to keep the level of annotation somewhat…

   possible for the Rust compiler 
   to infer most/all lifetimes)
I'd be interested to learn why you think this is possible. As you point out yourself, by Rice's theorem, precise lifetimes are not statically decidable. Rust's lifetimes are essentially based on nesting (think well-balanced brackets) and tracked by enriching the standard Damas-Hindley-Milner approach with a notion of affin-ness which is a weakening of Girard's linearity. Circular data structures immediately violate affine-ness. What mechanism do you propose to get around this conundrum?

Re: For Better Computing, Liberate CPUs from Garbage Collection

#123
post #64

Earlier quoted context omitted.

Reference counting is already slower than having a GC in most practical applications, not to mention that having no circular references may make the code where you need 'em either slower or means you'll have to write a workaround, which is often also overhead and makes things more complicated.

The benefit of not using GC is improved understanding of the code and a better architecture. These things will also lead to better performance. GC was a mistake. The main reason it is still used outside scripting languages is the notion that non-GC languages need to be low level. Which in practice is kind of true just because we haven't had any real competition in that area.

Not having GC in no way improves understanding of architecture or gives better performance. Hordes of C/C++ programmers that don't understand memory management but swear by malloc()/free() are a good example of that. And it's not like C/C++ are only language without GC, they are just popular now.

Typical programmer is taught nothing about memory management, till maybe they learn bits and pieces (often by hearsay and cargo culting). It doesn't matter if we're talking manual or automatic. Without such understanding one cannot write performant code or make a good architecture.

Also - a good working definition of low-level language is language that makes you care about things irrelevant to your task...

Re: For Better Computing, Liberate CPUs from Garbage Collection

#124

>> consumes a lot of computational power—up to 10 percent or more of the total time a CPU spends on an application. I stopped reading there. 10% is nothing. For such a useful feature as automatic garbage collection, for the vast majority of applications, I'd gladly give away 50% of the CPU. In terms of ensuring code correctness and robustness, if I had to choose static typing or automatic garbage collection, I'd pick…

10% is a lot. That's at least a few big cloud data center's worth of servers at this point. I'd gladly give the operators a reason to shut these down and save electricity.

Re: For Better Computing, Liberate CPUs from Garbage Collection

#125
post #81
post #27

Earlier quoted context omitted.

I have over a decade of professional experience entirely in C and C++. I believe that manual memory management is the wrong choice for the vast majority of applications. It is error prone and often slower than garbage collection.

if you have a decade of C then you know its not slower unless mistakes are made

if you believe that then you have no idea how Garbage Collectors work, period.

Re: For Better Computing, Liberate CPUs from Garbage Collection

#126
post #6
post #3

I’m probably wrong, but didn’t the Symbolics LISP machines have some kind of hardware support for GC? I think for platforms like Android this makes a lot of sense. Should help quite a bit with battery consumption and responsiveness. Also makes sense for server loads in Java or Go.

A https://en.wikipedia.org/wiki/Tagged_architecture yes. Tags make life a bit easier for the CPU when it accesses objects and is deciding what to do with them, but the CPU is still doing all the work and walk the RAM to do the GC. (I vaguely recall stories about Lisp machine users who would turn off GC while working, and then let it run when they left work and returned the next day.) The idea here seems to be to have…

There is a renaissance of that idea in ZGC [1].

You have a lot useless bits in a 64 bits pointers and thanks to the virtual memory, you can manage to have an untagged address and its corresponding tagged address referencing the same physical memory. This give you free bits that you can use to track the liveness/evacuation of a graph of objects.

[1] https://wiki.openjdk.java.net/display/zgc/Main

Re: For Better Computing, Liberate CPUs from Garbage Collection

#127

Seems like we could just as easily stop using garbage collection. ... or even go back to reference counting / smart pointers and just live with the “limitation” that we can’t have circular references.

Depending on the workload different memory allocation strategies perform better or worse. GC systems usually even have the fastest allocation. The only problem is that you see deallocation as one big block that is completely disconnected from allocation.

In throughput-optimized GC setups (not latency optimized) that's the case. Though free(), despite being seemingly "constant", can have unpredictable pause times as well when you hit a bad point.

Re: For Better Computing, Liberate CPUs from Garbage Collection

#128

Earlier quoted context omitted.

In my opinion, shared memory mutability is the actual bad idea that's going to eventually die. It's not just error prone, it doesn't scale; try mutating the same cache line from two threads on an Intel desktop chip and see how that goes. Let alone across mesh buses, chiplets, dual sockets or (God forbid) the network. Garbage collection on immutable data is vastly easier; it's intrinsically non blocking, concurrent an…

Au contraire , as memory, and hence workloads, get bigger, the cost of copying increases, and copying rather than sharing becomes ever more expensive. I just spoke with a physicist who told me that his current experiment produces 200 Gigabytes of data per second! Copying that amount of data around for immutability is inconceivable. Indeed the single biggest factor for performance for such workloads is minimising the…

Erlang style immutable reference counted shared memory is not at all state of the art. Persistent data structures are common and effective. I have implemented several myself, to store and update trees that don't fit in main memory. If you're updating one byte of your physicist's (say) 1 petabyte dataset, it requires ten memory allocations (log[branch factor] of the size of the dataset).

If you're updating the whole thing linearly, do consider that updating something in place or creating an updated copy is identical in terms of performance; a storage device doesn't care whether the bits streaming back are overwriting the same locations or new ones. Though of course you end up with both copies at the end.

Re: For Better Computing, Liberate CPUs from Garbage Collection

#129
post #9

Azul Systems has asked Intel to do this once... but instead created their own processors with interesting memory barrier properties for awhile that greatly sped up JVMs beyond what was capable (at the time) on x86-32/ppc/sparc. Eventually they gave up and became a purely software company, but their "Java Mainframe" product was many times faster than the Intels of the age executing the same code despite much slower CP…

Azul essentially provided tagged architecture AND I think forwarding pointers. The former gave you precise GC for free, the latter allowed concurrent GC to move data around without pauses.

Re: For Better Computing, Liberate CPUs from Garbage Collection

#130
post #6

Earlier quoted context omitted.

A https://en.wikipedia.org/wiki/Tagged_architecture yes. Tags make life a bit easier for the CPU when it accesses objects and is deciding what to do with them, but the CPU is still doing all the work and walk the RAM to do the GC. (I vaguely recall stories about Lisp machine users who would turn off GC while working, and then let it run when they left work and returned the next day.) The idea here seems to be to have…

There is a renaissance of that idea in ZGC [1]. You have a lot useless bits in a 64 bits pointers and thanks to the virtual memory, you can manage to have an untagged address and its corresponding tagged address referencing the same physical memory. This give you free bits that you can use to track the liveness/evacuation of a graph of objects. [1] https://wiki.openjdk.java.net/display/zgc/Main

Lisp Machines didn't use tags for tracking liveness/evacuation of objects, though. They used them for safety, which automatically gave them precise, as opposed to conservative, GC which always knew whether it was dealing with a pointer. They also had special, CPU-handled type of forwarding pointers, which when accessed "normally" would transparently redirect you to forwarded location.
Post reply on HN