7 ms·
> Having written services professionally in Java I have seen performance scale linearly with connections, until one day it suddenly spikes massively - why? It w
by weberc2 9y ago
> Having written services professionally in Java I have seen performance scale linearly with connections, until one day it suddenly spikes massively - why? It was that we crossed some threshold where the GC was suddenly having to do a ton more work, which caused a serious feedback loop - server has to pause, clients don't handle it well, clients hammer server more, server has to pause, etc.
Fair, but you almost never see things like this with Go, and when you do, it's pretty straightforward to triage since the GC and escape analysis are far simpler. Meanwhile, the performance is comparable.
> I find it far, far easier to write correct, expressive code in Rust.
I know this paragraph was comparing Rust to Java and not to Go, but while Rust is more expressive than Go, man does it take a long time to figure out how Rust wants you to express what you want to express. On the other hand, most things in Go do what you would expect, but sometimes you need to subvert the type system (which is a bummer, but it's worth it to me to sacrifice 1% of type safety for an order of magnitude or more productivity improvement).
- jashmatthews 9y ago> Fair, but you almost never see things like this with Go, and when you do, it's pretty straightforward to triage since the GC and escape analysis are far simpler. The Go GC is not a panacea. It trades lower STW pause times for a huge drop in throughput under GC pressure and simplicity for terrible performance with large, mostly static heaps when compared to a generational collector. This entire discussion and the original article is worth reading: https://www.reddit.com/r/programming/comments/5fyhjb/golangs_realtime_gc_in_theory_and_practice_pusher/dapa17l/ https://www.reddit.com/r/programming/comments/5fyhjb/golangs...
- weberc2 9y agoAgreed. My point is that those tradeoffs are really, really good for a huge swath of applications.
- jashmatthews 9y agoI'm not sure that's true. It works well for web proxies and simple CRUD apps. Anything which needs a decently sized heap is multiple times slower than Java, OCaml etc. CockroachDB only works at all because the actual DB is in RocksDB written in C++.
- weberc2 9y agoI don't know what constitutes "decently sized", but I've not had significant issues with a 12GB heap.
- pcwalton 9y agoHow exactly is the Go GC easier to "triage" than that of the JVM? Keep in mind that the HotSpot JVM does escape analysis just as Go does (this is sadly a very common misconception). The difference is that Go relies on escape analysis a lot more than the JVM does, because Go's GC has much slower allocation due to not being generational. > man does it take a long time to figure out how Rust wants you to express what you want to express. This goes away with experience. Certainly, most programmers get up to speed with Go faster than they do with Rust. But at this point the Rust language has totally melted away into the background for me.
- ngrilly 9y ago> The difference is that Go relies on escape analysis a lot more than the JVM does, because Go's GC has much slower allocation due to not being generational. True, but this is only a part of the story. In Java, every custom type is a reference type. This puts a lot of pressure on the GC because a lot of multiple small objects are created. Go has value types and doesn't suffer from this issue, which is a reason why having a generational GC is not that important for Go.
- littlestymaar 9y ago> This puts a lot of pressure on the GC because a lot of multiple small objects are created. … but they are allocated in the nursery, which isn't comparable to an allocation in Go (by orders of magnitude). It only makes a difference if you have a long-lived object (which must be tenured) and the difference is noticeable only if the object is small enough to be memcopied multiple times at low cost. That's why Go is only significantly faster than Java on the Go's marketing slides and not in real life.
- ngrilly 9y agoI already agreed that allocation is faster in Java than in Go. What I'm saying is that allocation speed is less critical in Go than in Java. In Java, if you allocate an object containing 10 other objects, you have to allocate 11 objects, because you only only have reference types (I know there is ongoing work to introduce value types). This is more work for the allocator, and for the GC. In Go, you allocate only once. Honestly, I'm not sure about this issue being very significant for most programs in either Go or Java. As a reminder, most C, C++ and Rust programs don't use a bump allocator either and they're doing well.
- littlestymaar 9y agoI have the opposite experience, Go's is pretty bad at reclaiming memory (I think that's the trade-of for not having long pauses), and we've been been bitten by lack of memory in production a few times. The solutions are : 1. allocate less, but this is not always straightforward since Go doesn't give you a fine control on memory allocation (compared to Rust). 2. change the VM tier to get more memory, what we eventually did.
- weberc2 9y agoIt's pretty easy to intuit about where allocations will occur in Go even though it's not explicit as in Rust, but you don't even have to intuit because Go's profiler does an excellent job of highlighting the allocations, and strategies for working around them are the same as in Rust. The profiling bit is harder than in Rust, but you only need to do this analysis in the hot path, while Rust requires you to make memory allocation decisions everywhere.