3 ms·
What an amazing read. These folks really pulled off some fantastic engineering without a JIT. It will be interesting to see if the team decides to add additiona
by collinf 8y ago
What an amazing read. These folks really pulled off some fantastic engineering without a JIT. It will be interesting to see if the team decides to add additional knobs to configure the Go GC for different workloads like Java has now.
- squiguy7 8y ago> We also do not intend to increase the GC API surface. We've had almost a decade now and we have two knobs and that feels about right. There is not an application that is important enough for us to add a new flag. It sounds like they don't intend to add any more tuning parameters for the time being. Considering they have made it this far without many ways to adjust the garbage collector, I'll bet this remains true.
- kjeetgill 8y agoGo has one BIG advantage compared to Java with respect to both JIT and GC. Go has structs. This introduces a little more complexity that Java chose (reasonably) to avoid by making everything a primitive or a reference. There isn't any "direct" objects or explicit pointers like Go has. This may muddy up the language vs Java a little bit, but it also gives a lot more tools to work your code around the runtime's limitations. And thats a perfectly fine design point by me. If you're going to have platform limitations (no JIT, simple GC) then I need reasonable tools when I hit them. It's much easier to avoid frequent allocations or implement arenas in Go. This takes the pressure of the runtime to be one size fits all. I know, I know, Java is getting Value Types some day! We'll see where that lands.
- staticassertion 8y agoIt's then interesting to compare to C#, which also can do stack allocation, but still chooses a generational GC.
- kjeetgill 8y agoI knew it had it but I have no C# experience. Does idiomatic code use this or only more niche optimizations?
- pjmlp 8y agoAll performance critical data structures are value types. Meaning int, long, char, bool, ..., points, rectangles, pairs, colours, enumerations. Then generics are reiffed. So each instance gets a copy if value types are used. Additionally, you can explicitly allocate value types and arrays on the stack and there are APIs for manual memory management.
- masklinn 8y agoC# defaults to reference types, structs are not usually recommended as the default way to build your own types, only as an optimisation.
- nemo1618 8y agoI love Go's value types. If you're careful/obsessive, you can write programs that don't allocate anything on the heap. That sort of power is really nice to have in a pinch.
- mike_hearn 8y agoI agree it's a good and well written talk. I enjoyed reading it. WRT knobs. Apparently they aren't going to do so, but I suspect that's a mistake. It's apparent from reading this talk that GC design for Go has often been constrained by this "no knobs" design philosophy in ways that seem problematic. For instance they designed a GC to have the shortest pauses possible, but then kept hitting throughput problems on a classic batch job where latency doesn't matter at all (their compiler). I wrote about this problem some time ago: https://blog.plan99.net/modern-garbage-collection-911ef4f8bd8e https://blog.plan99.net/modern-garbage-collection-911ef4f8bd... The essay points out that GC tuning exists because of fundamental tradeoffs between low pause times and throughput. Java lets you tune the GC precisely to avoid the nasty situation Go got itself into, where the demands of very very different kinds of workload (super latency sensitive Google servers vs compilers) are difficult to reconcile with each other. You can see this tension come through several times, like when they admit that they would have done a normal "enterprise" style GC as they rather condescendingly called it, but they felt Go's market position was under threat, they only had a year to make improvements but were constrained by the requirement to not slow down the Go compiler itself: So we were limited. We had basically a year of compiler performance improvements that we could eat up by making the GC concurrent. But that was it. We couldn't slow down Go programs. That would have been untenable in 2014 ... Go also desperately needed short term success in 2015. So they ended up with this design that they knew was kind of weird and not that great, but it let them promote low latency above all else to their users, and they sort of buried the tradeoffs they were making along the way. Which, reading between the lines, might have been related to internal staffing issues at Google - why else would a well funded project like Go have "desperately needed short term success in 2015"? It's not like they sell the Go compiler. More quotes that support this: As you can see if you have [request oriented collector] on and not a lot of sharing, things actually scale quite nicely. If you don't have ROC on it wasn't nearly as good. So they had a GC that scaled better. But it got killed by, you guessed it, the needs of batch jobs: But that wasn't good enough, we also had to make sure that ROC didn't slow down other pieces of the system. At that point there was a lot of concern about our compiler and we could not slow down our compilers. Unfortunately the compilers were exactly the programs that ROC did not do well at. We were seeing 30, 40, 50% and more slowdowns and that was unacceptable. Go is proud of how fast its compiler is so we couldn't slow the compiler down, certainly not this much. They could have solved this problem by having two GCs for Go programs tuned for throughput and latency, or doing what the Java guys did and trying to make an adaptive GC like G1 where you can give it pause time targets: if the target is very high then it tunes for throughput otherwise it tunes for latency. But instead they seem to have sacrificed it all on the altar of "no knobs", which is a pity because they ended up introducing two knobs anyway: SetGCPercent and SetMaxHeap. Well hey, guess what, if you use the G1 GC in Java you are only supposed to tweak two knobs too - max heap size (same as Go) and pause time target. If anything G1's knobs seem better because pause time target is a lot easier for developers to reason about than "heap overhead multiplier". In the end it's unclear their sacrifices were really worth it, although I don't know enough about Go to know what dire straits in 2015 were causing them to need such short term success.