4 ms·
> Just like synchronization, Go scales poorly with project complexity and aspirations. I've had the opposite experience. Compared to C++ codebases I've worked
by BobbyJo 2y ago
> Just like synchronization, Go scales poorly with project complexity and aspirations.
I've had the opposite experience. Compared to C++ codebases I've worked on, Golang has way less "complexity per feature".
> It is unable to efficiently take advantage of beefy many-core nodes
Go had the best built-in concurrency primitives of any language I've used (python, java, rust, c++/c).
> its GC is bad at achieving high throughput
Isn't this just the nature of using GC? You give up control over when some work gets done, of course it affects throughput.
> incapable of providing zero-cost abstractions
ime, bad abstractions slow systems of any appreciable complexity a lot more than the cost of the abstractions in latency.
> non-zero cost abstractions end up being more expensive than in other compiled languages.
Do you consider Java a compiled language? I mean, of course its slower than rust and c/++, as it has a more complex/abstracted runtime. But last I heard, it was on par, or even faster, than java.
- TylerE 2y agoPlus the usual mistake of assuming (re: GC) that the system (de)allocators are free. They weren’t. I strongly suspect that GCs are extremely competitive in most non-trivial applications. Don’t judge every GC based on experience with the Sun JRE 20 years ago.
- neonsunset 2y agoThey are, but not so much in the case of Go - it is optimized for small containers with few CPU cores, that do not need to sustain (inevitable) high allocation throughput. This is what happens when it's in different conditions, in a test that is still very friendly to Go using the stack which it's supposed to be very strong at: https://github.com/LesnyRumcajs/grpc_bench/discussions/441 https://github.com/LesnyRumcajs/grpc_bench/discussions/441 Note the CPU % usage. The numbers only get more interesting once you start using 64 core hosts. You could also look at write barrier/synchronization/allocation sensitive microbenchmark instead which paints way less positive picture: https://benchmarksgame-team.pages.debian.net/benchmarksgame/performance/binarytrees.html https://benchmarksgame-team.pages.debian.net/benchmarksgame/... (special props to OpenJDK's write barrier elision, this is something .NET needs to do better at still)
- jpgvm 2y ago> it was on par, or even faster, than java. This is rarely the case outside of very simplified cases. Golang prioritises compilation speed over optimisation. Unlike Rust/C/C++ which either use one of the heavily optimising IR compilers (gcc or LLVM) Golang uses neither, preferring to implement piecemeal the optimisations that work well on relatively simple code - in order to keep the compiler very fast and simple. Java is the opposite of this. It has multiple compilation stages, the first of which is the bytecode compiler javac but then also the runtime JIT compiler, both of which favor peak performance (i.e optimisation). Golang can appear faster on many micro-benchmarks but for any highly numeric load or remotely generic code using interfaces etc become involved then Java is going to come out on top and it won't be particularly close. This isn't to say you can't write very fast Golang code, you can. If you understand (or simply inspect generated code/profile) what the compiler can and can't do for you you can coax it into making fast machine code but you need to be vigilant and modifying tight loops can be more troublesome than equivalent fast Java code. I have written very fast stuff in both languages and if I needed to pick a language for peak runtime perf it would be Java out of those two every time. Note this is completely ignoring the very weak throughput of the Golang GC which is another easy way to get into very bad performance problems with Golang that can be hard to resolve.
- erik_seaberg 2y agoThe JVM provides a lot more flexible concurrency abstractions, but they're now appearing in the standard library instead of hardwired into the language. This lets us extend or reimplement them. (Synchronized blocks/methods are primitive and haven't been deprecated, but they recommend using java.util.concurrent.locks instead.)