3 ms·
>>Go is faster than Java / C#, more memory-efficient than Java / C# >Look up any set of benchmarks online and you'll find this claim to be mixed at best. I do
by mtlynch 4y ago
>>Go is faster than Java / C#, more memory-efficient than Java / C#
>Look up any set of benchmarks online and you'll find this claim to be mixed at best.
I don't know a ton about low level performance, but I'd find it surprising if it's not true. How can interpreted bytecode outperform direct machine instructions?
The benchmarks I've found have Go outperforming Java and C# in almost every test.
https://benchmarksgame-team.pages.debian.net/benchmarksgame/fastest/go.html https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
- phs2501 4y ago> I don't know a ton about low level performance, but I'd find it surprising if it's not true. How can interpreted bytecode outperform direct machine instructions? No production Java/.NET runtime directly interprets bytecode, it gets dynamically compiled into machine code. And as a result it can dynamically _recompile_ it if it discovers runtime profiling patterns that mean a different compilation can run faster, it can dynamically inline functions into the compilation if pertinent, etc. This does not mean that Java/.NET code _will_ always run faster than native static compilation (a quick gander at the real world shows that optimized production code is usually pretty close either way), but it explains how it _can_ run faster.
- mtlynch 4y ago>No production Java/.NET runtime directly interprets bytecode, it gets dynamically compiled into machine code. And as a result it can dynamically _recompile_ it if it discovers runtime profiling patterns that mean a different compilation can run faster, it can dynamically inline functions into the compilation if pertinent, etc. Oh, didn't know that. Interesting, thanks!
- vvanders 4y agoTo take this even further, it's not the code that matters as much but the data access patterns and being able to have structured access patterns in ways that preserve cache locality. C# actually does really well on this front in that it brings in value types front-and-center, although similar types of capabilities exist in Java(either through ByteBuffers or sun.misc.Unsafe) if a bit harder to use.
- adgjlsfhk1 4y agoI do find it really interesting that there was a whole generation of languages that forgot that memory layout mattered. the typical OO pile of pointers is about as bad as you can possibly imagine.
- kaba0 4y agoTheir memory layout patterns are not worse than the stereotypical C program with their linked lists due to its inability to have even a proper vector data structure.
- lelanthran 4y ago> No production Java/.NET runtime directly interprets bytecode, it gets dynamically compiled into machine code. True, with the caveat that: 1. Compilation occurs while the program runs, using some CPU power 2. Compilation occurs on those parts of the code that pass certain criteria for being a hotspot 3. Because of #2, some CPU power has to be used for profiling continuously as the program runs It can be faster than AoT compilation, but AoT can do much more aggressive optimisations because AoT compilation can use all available CPUs, for as much time as they want to. JiT compilers have to balance the processing power used for compilation against leaving some processing power for the actual program. JiT performs very well on benchmarks because: 1. It's a small piece of code, run serially (thereby leaving one entire other core just for profiling and compilation) 2. That one small piece of code is run dozens of thousands of times, triggering the JiT compiler to optimise that "hot spot". 3. The "hot spot" is the only code to run so the entire program is very quickly turned into a native-code program, with the best optimisations that the JiT compiler can perform. In practice (i.e. not benchmarking), the code is large, it doesn't run serially, it uses all cores (especially in performance sensitive applications) and the JiT compiler and continuous monitoring will effectively steal processing power from the program. In benchmarks, the JiT compiler is not using any power that the program would have used. > And as a result it can dynamically _recompile_ it if it discovers runtime profiling patterns that mean a different compilation can run faster, it can dynamically inline functions into the compilation if pertinent, etc. There's a lot of "if"s there. They all have to line up perfectly to get well-optimised native code. > This does not mean that Java/.NET code _will_ always run faster than native static compilation (a quick gander at the real world shows that optimized production code is usually pretty close either way), but it explains how it _can_ run faster. It can run faster, but that is rare outside of the benchmark environment - it's more likely to run as fast as AoT compiled programs, because the throttling factor in most programs is the data access patterns, not the computation. In practice, for the usual type of program, you're not likely to notice much of a difference (other than startup time) between AoT programs and JiT programs.
- kaba0 4y agoGo’s compiler pretty much just spews out machine code, it barely does any optimizations, so in this case this comparison is meaningless.
- danielheath 4y ago> How can interpreted bytecode outperform direct machine instructions? Without opining on whether it does, it definitely can, because the Java JIT compiler has access to runtime information unavailable to the go compiler - which enables more aggressive optimisation on hot paths.
- mtlynch 4y agoAh, I see. I hadn't thought of that. Thanks!
- pcwalton 4y ago> I don't know a ton about low level performance, but I'd find it surprising if it's not true. How can interpreted bytecode outperform direct machine instructions? Because the JVM and .NET compile; they don't interpret bytecode.
- kjksf 4y agoThat doesn't mean that JVM or .NET JIT is faster than Go compiled code. They will almost always be slower because they have 3 structural disadvantages. 1. Compilation bytecode => machine code happens at runtime so it's a constant overhead. There's also other overhead related to keeping invocation counts to decide when JIT should kick in. 2. Because compilation happens at runtime, they can't spend too much time on compilation so they are limited at how good the generated code can be. Go doesn't have those restrictions. 3. Modern performance is heavily influenced by memory use. By design JVM and .NET are more memory hungry. Every object in JVM has 8-16 bytes overhead compared to Go struct etc. Value types are relatively recent and not commonly used. In practice it adds up. The are 2 advantages of advanced JITs: 1. It can make better inlining decisions based on actual execution counts of a function vs. a heuristic in a Go compiler. (Go 1.20 will have preview of profile-guided optimization which provides the same optimization). 2. A generational GC used in most JVM / .NET implementation is faster for certain allocation patterns (high rate of allocations / frees) than Go's allocator. But your average Go program will be both faster and significantly less memory hungry than your average Java / .NET program. The memory overhead is especially bad for Java / .NET. Go only compiles the functionality used. Java / .NET have very heavy runtimes / standard libraries that are packaged into one library and have to be loaded into memory. What it means in practice is: I can run a Go server comfortably on the cheapest shared server with 512 MB and a Java / .NET server would push it to the limit.
- kaba0 4y agoA managed language directly trades away memory usage for CPU time and vice versa. Go using less memory only means it will have worse throughput.
- pjmlp 4y ago.NET has had Go like structs since 2001. Value types in .NET exist since 2001. .NET has unsafe since 2001. .NET has had AOT since 2001 with NGEN. C++ is one of the supported languages on .NET since 2001. Please educate yourself on the platforms, before criticising them.
- kovac 4y agoNot sure if C# can beat Go in real-life applications but C# has advanced features that can contribute to performance: - JIT and runtime optimizations - AOT compilation if you want it (probably contends Go's native compiled code?) - Access to raw pointers that lets you do things like pinning things in memory and intervening with normal GC - hardware intrinsics for SIMD support C# comes with some serious performance knobs if you're really committed to writing performant code.
- pjmlp 4y agoLess so since the ongoing improvements since version 7, but if something more beyond C# low level capabilities is required, there is C++/CLI as well. Currently compliant with C++17.
- igouy 4y ago> The benchmarks I've found have Go outperforming Java and C# in almost every test. The C# measurements from the same source don't seem to show that? https://benchmarksgame-team.pages.debian.net/benchmarksgame/fastest/go-csharpcore.html https://benchmarksgame-team.pages.debian.net/benchmarksgame/...