Live data from Hacker News

Go does not need a Java-style GC

erik-engheim.medium.com

111–120 of 226 posts

Re: Go does not need a Java-style GC

#111
post #65

Earlier quoted context omitted.

"Scalar replacement" explodes the object into its class member variables and does not construct a class object at all. That does result in the exact same `sub %esp` (that Go would do for any struct), but it is restricted to only working if every single usage of that class type is fully inlined and the class is never passed anywhere that needs it in its object form. It's worse than what Go has. Go can stack-allocate a…

Scalar replacement does not work even in very trivial cases: https://pkolaczk.github.io/overhead-of-optional/ In all those cases, Optionals were inlined, didn't escape, yet they haven't been properly optimized out.

[deleted]

Re: Go does not need a Java-style GC

#112
post #6

> In a multithreaded program, a bump allocator requires locks. That kills their performance advantage. Java uses per-thread pointer bump allocators[1] > While Java does it as well, it doesn’t utilize this info to put objects on the stack. Correct, but it does scalar replacement[2] which puts them in registers instead > Why can Go run its GC concurrently and not Java? Because Go does not fix any pointers or move any o…

Scalar replacements (as currently implemented in Java) does not work in real-world programs. Well-written code does not need it. Poorly written code can not trigger it, because the JIT is too dumb and isn't getting better. There is no sane test to determine whether a piece of code will be inlined in Java. In practice anything more complex than byte array is unlikely to be inlined. Even built-in ByteBuffers aren't! Me…

[deleted]

Re: Go does not need a Java-style GC

#113
post #38

Earlier quoted context omitted.

There's still a memory tradeoff, some due to GC, some due to Java (lots of runtime reflection...). Guessing 2-4x.

This is a bit of a tangent, but you can get into situations where Java's memory-overhead becomes pretty untenable. I was in a situation of having to keep track of ~1 billion short strings of a median length of maybe 7 characters. In terms of just data, that should clock in at about 10 Gb; in practice it was closer to 24 Gb. I tried going with just byte[]-instances instead, which didn't help a lot. Using long byte[]-i…

A factor of 2.4 is extremely unlikely to be what makes the difference between a program being viable and not. You have to be in an extremely fine-tuned situation for that to make the difference, and unless your usage level is unusually static it's probably only going to make the difference for a few weeks or months.

Re: Go does not need a Java-style GC

#114

> In a multithreaded program, a bump allocator requires locks. That kills their performance advantage. Wait, what? What's wrong with: char theHeap[0x1000000]; atomic_ulong bumpPtr; void* bump_malloc(int size){ uint32_t returnCandidate = bumpPtr.fetch_add(size, std::memory_order_relaxed); if(returnCandidate + size >= HEAP_SIZE){ // Garbage collect. Super complicated, lets ignore it lol. // Once garbage collect is done…

Even with relaxed memory ordering, you’re still bouncing the cache line around between every CPU that tries to access bumpPtr. I would expect that to be significantly slower than using per-thread heaps (especially if you have a large number of CPUs).

Re: Go does not need a Java-style GC

#115

The binary-trees benchmark on The Debian Language Shootout[1] involves allocating millions of short-lived trees and traversing them. It is informative about GC performance even with the caveat that there are 'lies, damned lies, and benchmarks', because many real-world graph analysis and brute force tree search algorithms similarly allocate zillions of short-lived nodes. For non-GC languages like C/C++/Rust it gives a…

Look at the Go benchmark program: https://benchmarksgame-team.pages.debian.net/benchmarksgame/... Needs to be faster? Use a pool like the C benchmark programs, but super simple: just a slice, local to the goroutine. Trivially make the Go program 10x faster, 5 minutes of work, a few edits: type Tree struct { Left int Right int } func itemCheck(id int, pool []Tree) uint32 { tree := &pool[id] if tree.Left != -1 && tree.…

Several (about 10) years ago, I submitted essentially the same program. It was one of the fastest of all the implementations across all the languages.

However, Isaac rejected it, saying it violated the conditions.

Re: Go does not need a Java-style GC

#116
post #37

Earlier quoted context omitted.

Max pause times of 0.5ms is what got me really interested. It feels like a huge trade-off of GCs is almost completely gone. https://malloc.se/blog/zgc-jdk16

> It feels like a huge trade-off of GCs is almost completely gone. FWIW the tradeoff of low latency GC is usually paid in throughput. That is definitely the case for Go, which can lag very much behind allocations (so if your allocation pattern is bad enough the heap will keep growing despite the live heap being stable, because the GC is unable to clear the dead heap fast enough for the new allocations).

throughput can be fixed by adding compute. latency cannot. always optimize for latency with gc.

and no the heap will not keep growing in golang. it'll force threads to help with GC if its falling behind. thereby reducing the rate of allocations and speeding up the collection.

Re: Go does not need a Java-style GC

#117
post #40
post #38

Earlier quoted context omitted.

There's still a memory tradeoff, some due to GC, some due to Java (lots of runtime reflection...). Guessing 2-4x.

Also, throughput. But latency and throughput are almost universally opposite ends of the same axis — that’s why it’s great that Java allows for choosing a GC implementation.

you can fix throughput problems by adding compute resources, you can't fix latency issues. I'll always pick a GC that optimizes latency over throughput. its easier to maintain the software.

Re: Go does not need a Java-style GC

#118
post #10

Cool article, I'm not sure I agree with the headline. I used to write low-scale Java apps, and now I write memory intensive Go apps. I've often wondered what would happen if Go did have a JVM style GC. It's relatively common in Go to resort to idioms that let you avoid hitting the GC. Some things that come to mind: * all the tricks you can do with a slice that have two slice headers pointing to the same block of memo…

How have you found Go in contrast to Java. Is the simplicity worth it?

yes. golang is actually less restrictive than java. and avoids a ton of the bullshit abstractions you see in every java code base.

Re: Go does not need a Java-style GC

#119
post #109

Did Go ever fix that problem where short term high memory usage can cause large empty heaps because of the lack of compaction? I remember a rash of articles about this phenomena a while back. This article seems to think its not an issue so I'm wondering when it was fixed.

that was never an issue? maybe your thinking of the slowness golang had in returning memory to the OS? that was resolved.

Re: Go does not need a Java-style GC

#120
post #75
post #62

I guess it is the same reasoning like Go not needing generics.

No, it is same reasoning as Java not needing dense memory layouts

No, Java folks never denied they were eventually needed, in fact IBM has had the object layout extension on their implementation for almost a decade now.
Post reply on HN