20 ms·
Go’s march to low-latency GC
- anonymousDan 10y agoSo how does the GC performance of Go compare to something like Java/the Hotspot JVM?
- geodel 10y agoTechnically hotspot GC might do more work in same amount of time but Go's GC makes some performance guarantees like <10ms STW phase which hotspot do not claim or offers for large heaps.
- sievebrain 10y agoYes, but that's because the Go GC doesn't compact, and nobody quotes throughput numbers. Building a slow GC that leaves the heap fragmented but has short pauses is not that difficult indeed, the tricky part starts when you wish to combine all these things together.
- geodel 10y agoOf course Java has all technical bullet points checked and may be superior GC from strictly that point of view. But Go has 2 things from users' perspective upfront which Java lacks. 1. It uses about an order of magnitude less memory than Java. 2. It openly proclaims <10ms STW pauses for GC.
- kasey_junk 10y agoThe lack of compaction is not just a bullet point. Especially on large memory data-sets Go's GC will start to suffer and not just on the collection side of things but on the allocation side as well.
- weberc2 10y agoHow do you mean? The 1.5 benchmarks showed Go cleaning up a 250GB heap in 5ms.
- kasey_junk 10y agoYour allocation times will go up as the heap gets fragmented and the it becomes harder to find places to put new items. This is especially true of large interconnected data sets. Further, depending on your data access patterns you can see data access start to degrade over time as well because the memory locality is worse. GC benchmarks are great at showing how well 1 part of memory management is behaving (ie the deallocation step) but it doesn't do much for talking about the other 2 parts, allocation and access. That said, I use Go lang every day and the GC improvements to date have been great, especially given the kinds of memory patterns lots of the services I write have (small, short lived items that aren't really connected to each other). But there are definitely memory patterns where Hotspot will smoke the golang memory system and that doesn't begin to describe something like Zing.
- weberc2 10y agoCool, thanks for the information. :)
- uluyol 10y agoIt would be nice to quantify what the impact of this is. Go is no worse in this regard than C++ (it even uses a fork of tcmalloc for allocation) and has support for value types so there is a lot less pointer chasing than in Java. Not sure how it could be done but having some numbers on this would be great.
- geodel 10y agoZing is not some magic. To start with it needs heavily over provisioned servers with like 64GB+ RAM recommended. And to have the pauseless GC it needs additional contingency and pause prevention memory pools on top of -Xmx memory settings. And still I have heard the one of the best way to control GC in many trading systems where Zing might be popular is to just provision 100s of GBs of memory heap and simply restart server once trading day is over.
- mdasen 10y agoGo definitely does not use "an order of magnitude less memory than Java". That would mean that a Go program that uses 1GB of memory would need 10GB in Java. Google wrote a paper comparing C++, Java, Scala, and Go and definitely did not find that (https://days2011.scala-lang.org/sites/days2011/files/ws3-1-Hundt.pdf https://days2011.scala-lang.org/sites/days2011/files/ws3-1-H...). I like Go and it has many wonderful qualities. Still, it's important to be realistic.
- lossolo 10y agoIn my experience it does use less memory than Java. I had application written in Java which i migrated to Go and i see less memory usage.
- geodel 10y agoWell depending on program. Here is what I see. https://benchmarksgame.alioth.debian.org/u64q/go.html https://benchmarksgame.alioth.debian.org/u64q/go.html
- igouy 10y ago"When there's a big disparity between those Java and [Go] programs, it's mostly the default JVM memory allocation versus whatever [Go] needs." http://programmers.stackexchange.com/questions/189542/is-memory-management-in-programming-becoming-an-irrelevant-concern/189552#189552 http://programmers.stackexchange.com/questions/189542/is-mem...
- geodel 10y agoI looked at this: http://stackoverflow.com/questions/5673388/what-is-the-smallest-you-can-make-a-oracle-jvm-java-heap http://stackoverflow.com/questions/5673388/what-is-the-small... For me using Java 1.8 the number is around 1.5MB. Something similar in Go is 60KB
- richard_todd 10y agoI think for "small-data" programs it does work out to about an order of magnitude of overhead in Java. I have ported several small Java programs to Go and I see it (like 100MB Java vs 8MB Go). One encryption program I coded multiple versions of ran 350k C vs. 1.3MB Go vs. 16MB Java. Programs holding GBs of data in arrays would look much closer, though, I imagine, as the overhead would be dwarfed by the data itself.
- the8472 10y ago> 2. It openly proclaims <10ms STW pauses for GC. Java's GCs make no concrete claims because they scale from tiny to very large heaps with vastly different object populations and root set sizes. Some java applications run with 100GB heaps or on 128-core NUMA machines with lots of threads. 10ms pause times are achievable with "modest" heap sizes (~single-digit GBs) if you have some cores to spare for a concurrent collector to do its work, well, concurrently. If you don't have enough spare CPU time or have a larger heap or a workload without enough breathing room then it would be silly to make such guarantees. Of course they could easily write "<10ms STW pauses. sometimes. read the fine print"
- pcwalton 10y agoHotSpot does offer that. It's basic functionality that all incremental or concurrent garbage collectors offer. You can adjust the max pause time with -XX:MaxGCPauseMillis.
- pas 10y agoThat's a target. (GC ergonomics) It won't guarantee it, just tires to size things (eden space, survivor spaces) and time things to meet its target. But it's a fickle beast. And usually it requires a lot of tinkering with the code for it to be able to meet it. And then it's easier to disable ergonomics, set fixed sizes, and just enjoy how blazingly fast CMS is, restart the app every few weeks (CMS heap fragmentation), and try G1 with every new point release, maybe finally it beats CMS.
- _ph_ 10y agoThe approaches to GC are difficult to compare, and Java offers a selection of garbage collectors. Overall, the Java collectors are very sophisticated and tuned over years, so in principle are excellent. The downside is, that the Java language itself puts a lot of stress on the GC. The biggest problem is, that Java offers no "value" types beyond the builtin int, double,... So everything else has to be allocated as a separate object and pointed to via references. The GC then has to trace all these references, which takes time. While a collection of the youngest generation in Java is extremely fast, a global GC can take quite some time. Go on the other side has structs as values, so the memory layout is much easier for the GC. Go always performs full GCs, but mostly running in parallel with the application, a GC cycle only requires a stop-the-world phase of a few milliseconds (for multi gigabyte heaps). All these numbers of course depend a lot on what your application is doing, but overall Go seems to be doing very well with its newest iterations of the GC.
- Cyph0n 10y agoAnother strong point for the JVM is the availability of alternate implementations from several vendors. Is this possible for Go say in the future?
- _ph_ 10y agoIt is certainly possible. There are already two Go implementations, the official one, and a gcc based one. And due to the fact that the whole Go implementation is available under BSD license, allows anyone without any license worries to fork a custom Go implementation.
- lloeki 10y agoYou forgot GopherJS.
- arcticbull 10y agoThere's also llgo.
- sagichmal 10y ago
- deleted 10y ago[deleted]
- nvarsj 10y agoA significant drawback of the hotspot JVM is the amount of memory required for even simple apps. At least 64Mi for the most simple, and typically much higher. A typical web app with a 1000 request threads will use something like 1.5Gi of memory (512Mi heap, 1Gi for thread stacks, classes, etc). Golang apps tend to happily run with less than 100Mi, so are well suited as daemon processes that don't get in the way. However if you need to support a large amount of dynamic state (> 1Gi), the hotspot GC is very difficult to beat.
- sievebrain 10y agoMemory usage in Java can be misleading. Some versions of the JVM will happily take ALL your free RAM if it thinks it's sitting there unused because there's a RAM/CPU tradeoff in garbage collected systems: the less frequently you GC the less CPU time you burn and the faster the app runs. If your machine actually does have gobs of free RAM, it therefore makes sense for Java to use all of it. If your machine has gobs of free RAM you were planning on using for something else after your Java app started, well, that's something the JVM couldn't know. Some versions (on Windows?) monitor free memory and adjust down its own usage if you seem to be consuming the headroom, but on other platforms, you just have to tell Java it's got a limit and can't go beyond it.
- 102030485868 10y agoUnless you specifically tell the JVM otherwise using the -Xmx flag. See: https://docs.oracle.com/cd/E13150_01/jrockit_jvm/jrockit/jrdocs/refman/optionX.html https://docs.oracle.com/cd/E13150_01/jrockit_jvm/jrockit/jrd...
- _ph_ 10y agoAnother very nice feature of Go is, that since 1.5, the whole runtime, including the GC is written in Go itself. So every Go developer can look at the implementation. The GC itself is surprisingly small amount of code.
- knorker 10y agoIt's not yet idiomatic or good Go code now, though, is it? IIRC the initial state (1.5) was mostly machine translated code from C to Go.
- _ph_ 10y agoThe main thing is, that they machine translated the Go compiler itself from C to Go, so the compiler had not so great Go code. The rest of the runtime probably was already human-written in Go before that. And of course, anything which has been under development since then is human written, like the new SSA-based compiler.
- EdiX 10y agoThe rest of the runtime probably was already human-written in Go find -name '*.X' | xargs wc -l in src/runtime says Go 1.4: 21701 .c 33348 .go 19160 .s Go 1.7b2: 3340 .c 77597 .go 33827 .s The assembly growth seems to be attributable to the increased number of supported platforms
- 4ad 10y agoYou should exclude runtime/cgo, since it's not relevant.
- giovannibajo1 10y agoThere's also an increased number of optimized code-paths, like for instance some crypto code in the TLS stacks. The natural way to optimize Go code, for instance to benefit from advanced CPU instructions in modern architectures, is to fallback to assembly.
- thegeekpirate 10y agoPosted earlier without the random hash in the URL https://news.ycombinator.com/item?id=12040349 https://news.ycombinator.com/item?id=12040349
- ben_jones 10y agoThis may be anecdotal but Twitch is an example of a service that just bloody works. I've been a user for awhile and I've yet to notice any noticeable service disruptions or issues. They were also one of the largest early adopters of EmberJS, pretty sure it was well before the 1.0 release when many bugs were still being worked out and the API suffered frequent changes, so hats off to the engineering team for continued awesome work.
- hdra 10y agoMaybe if you have fast internet connection. I'm on a HSDPA+ connection and Twitch is unusable, not even the VODs. Then again, Youtube and Vimeo is pretty much the only sites from which I can watch video streams smoothly.
- nindalf 10y agoWhat's your location? I've found the same - I can stream HD on Youtube gaming without an issue but not anything better than Twitch Medium. Sometimes I need to downgrade to low or mobile quality to keep up. I figured it was because of my location (not EU or NA).
- predakanga 10y agoI'm curious, have you tried viewing the streams or VODs through an alternate player? I've found that I can almost always improve the smoothness of their content by using Livestreamer[0] to play it in VLC (or Kodi, more often) [0]: http://docs.livestreamer.io http://docs.livestreamer.io
- 83457 10y agoI use this on my netbook. Pretty much unwatchable otherwise
- lossolo 10y agoIt doesn't have anything to do with the topic. It's quality of their network or quality of yours that is the main reason here. Not software.
- pepesza 10y agoI think that not using Erlang in this particular case was a mistake. Erlang is running some of the largest chats out there, including League of Legends and WhatsApp. They would have avoided all the hassle of GC pauses, since Erlang has per-process GC collection. And scaling single OS process to their number of connections was done for Erlang machines years ago.
- gnuvince 10y agoIsn't Facebook's chat also powered by Erlang?
- kevincox 10y agoIt definitely was when it originally launched. After that I have no idea.
- nocarrier 10y agoThe Erlang components of Facebook Chat were replaced with C++ several years ago. The two main reasons I remember are A) it was hard to maintain a group of engineers with acceptable competency in Erlang over time and B) the C++ code offered faster and more consistent performance albeit with somewhat less scalability in terms of sessions per host. We just added X% more servers to the channel pools and were happy to have the chat services in a language where more FB engineers could contribute. There's been a lot more changes in the architecture than just moving to C++ though, so it's hard to do a direct comparison between the products. This doesn't take anything away from WhatsApp though, who has built a strong product and infrastructure on top of Erlang.
- weberc2 10y agoThere are likely other tradeoffs. This (GC pause times) is probably not the only criterium, nor even the most important. It's really hard to draw a conclusion based on such limited information.
- jerf 10y agoPossibly in the past, yes. But if they're now just paying 1ms in GC every so often, the advantage is now gone. Go is generally faster than Erlang (in Go-native vs. Erlang-native code) so the system is quite possibly net outperforming what Erlang can do now. 1ms is just noise when packet latency jitter is higher than that.
- r1ch 10y agoI have to wonder - when you're digging down into this level of complexity in order to discover issues with the language you're using, wouldn't something like C be better? IRC isn't a very hard protocol and you know the language won't be getting in your way if you're using C.
- daenney 10y agoBetter in what way? Performance wise, perhaps but that's only one aspect of why someone might pick one language over another. Even distilling better down to just the max throughput you can get for a solution in a language vs another is hard to do as a lot also depends on how the code ends up being written and how easy you want to be able to debug that solution. You can solve this stuff in C many ways with different performance characteristics.
- jjnoakes 10y agoAt scale it may be more efficient to write the system in a higher level language (saving time) and then spending some time tuning only the slowest parts, instead of building everything from the start to be highly optimized, even the parts which may not need it (investing time where it may not produce results). And the improvements to Go that they drove will help everyone. I happen to prefer C, but I understand why they did it the way they did it.
- karma_vaccum123 10y agoThen we might be in some alternate reality talking about how Twitch could never deliver a viable service because the developers kept creating segfaults. C is the last language I would choose in a race to a viable service.
- _pmf_ 10y agoPurposefully strolling to where the puck was in 2001.
- mkevac 10y ago> Next up is runtime.scanobject. That function does several things, but the reason it’s running during the chat server’s mark termination phase in Go 1.5 is to implement finalizers. How did you know that? > We emailed back and forth and the Go team was very helpful with suggestions on how to diagnose the performance problems and how to distill them into minimal test cases. Can you give us the link?
- fauigerzigerk 10y agoThat's interesting, but it would be even more interesting if the article contained some info about heap sizes, memory utilization and the number of CPU cores.
- deleted 10y ago[deleted]
- amelius 10y agoHow do they prove correctness of their GC?
- coldtea 10y agoThey run lots of programs and see if they crash/leak. (Seriously, Go is not really an academic language caring for that kind of stuff, unless it comes off easily to prove it).
- iamleppert 10y agoI'm curious why you didn't just use something like Redis for managing concurrent state and pair that to any of the various web apps that are good at concurrent connections? You could still use Go to serve the web requests/sockets/etc.
- smegel 10y ago> But this isn’t another article about how great Go is for us — it’s about how our use of Go pushes the limits of the current runtime implementation in some dimensions, and how we respond to reaching those limits.
- lllorddino 10y agoBefore Go I was web developing in Node.js but wanted to get "closer to the metal." Thought about using C for the back end but then heard about Go and have been in love ever since. My favorite programming language by far.
- jeffdavis 10y agoThere has been a ton of research for GC on the JVM. What are the differences between Go's approach and Java's? Are those differences due to linguistic differences or different goals?
- cbsmith 10y agoThere was a ton of research of LISP & Smalltalk GC's prior to the advent of the JVM.
- jeffdavis 10y agoSo what are the trade-offs? Is each language re-inventing the wheel, or is it just a matter of implementation effort?
- cbsmith 10y agoI've found each language, out of expediency, often starts with a comparatively crude implementation of GC, and then gradually improves upon their work, leveraging knowledge from other platforms. That said, gc is very subtle, and each runtime has unique characteristics that mean that what works best for one might not be ideal for others.