Go has a global mark and sweep GC. OTOH Rust has a thread local, optional GC.
You can certainly control the GC somewhat. For example, disable unpredictable automatic GC and run GC yourself at a more opportune time, or never (if the program terminates before consuming all swap space of course).
I have one app where I loop continously and invoke the GC every second. Why so often -- crazy, right? No because the "garbage" generated over that second --thanks to some memory-aware development practices-- is minimal, so the GC call will typically return in way under 1ms. Of course that's a meaningless number without app context and other numbers, but you do get some control.
Basically Go gives you both philosophies. On one hand, you can auto-GC and never worry about mem or perf and simply "code out" your need, like you would in Java/C#/Python etc. Or, you can carefully design data structures and operations with allocations and GC (or supressed/non-existing GC) in mind. Sure, you don't get direct access to malloc()/free(), but implicitly (via Go's data structures, struct values vs pointers etc etc) you have a great deal more control over memory accesses, allocations etc.
Go provides much better static guarantees and much better speed than Python/Ruby/JavaScript, without having to spend any time learning about the type system. However, Go's weaker type system doesn't appeal to a lot of people used to more powerful type systems.
Citation?
Python is an interpreted language that runs on top of a virtual machine (usually CPython). Types are determined at run time.
.py -> .pyo* (bytecode) -> VM -> OS
On the other hand, Go (and other C languages) have a different runtime stack: .go -> binary* -> OS
Between source and binary are a bunch of compiler steps[0], but * is where both binaries are executed. Statically compiled languages do not have to determine types at runtime and therefore are able to optimize code paths much better.Still don't believe me? Here's a Fibonacci calculation micro benchmark[1] I ran:
╭─ting@noa /tmp/fib ‹python-2.7.3› ‹ruby-1.9.3›
╰─➤ time ./go
1346269
real 0.02s
user 0.01s
sys 0.00s
╭─ting@noa /tmp/fib ‹python-2.7.3› ‹ruby-1.9.3›
╰─➤ time python3 ./fib.py
1346269
real 0.61s
user 0.60s
sys 0.00s
Sidenote:Java runs on a virtual machine (JVM) but it's performance comes very close to C languages due to static typing, JIT compilation, and heavy investment in the JVM from many companies.
[0]: For C, compilation goes through these steps:
hello.c
(preprocessor)
hello.tmp
(compiler)
hello.s
(assembler)
hello.o
(linker)
hello <-- binary to run
[1]: https://gist.github.com/wting/77c9742fa1169179235fPyPy uses JIT to improve Python run time speeds but it's still magnitudes slower than statically typed languages.
I've upped n to 40 and rerun with the following languages:
C: 0.38s
Java: 0.55s
Go: 0.90s
Rust: 1.29s
LuaJit: 2.19s
Haskell: 8.97s
PyPy: 10.06s
Lua: 22.87s
Ruby: 22.13s
Python2: 43.88s
Python3: 66.28s
All code is available in the previous mentioned gist:But anyway, in my (limited) experimentations with LuaJIT, it's often been within a factor of 2x-3x of speed of C, which to me is pretty fast, and typical of many statically-typed, compiled languages.
C interpreter -> http://root.cern.ch/drupal/content/cint
Java compiler to native code -> http://www.excelsior-usa.com/jet.html
However, reality is that most languages' ecosystems and performances are tightly connected to one or two implementations.
I find sad that young generations mix languages with implementations and get wrong concepts that a certain language can only be implemented in a specific way.
Yes, but the parent that you responded to wasn't really susceptible to this. It's quite natural to speak of the "performance properties of Language X" as if you were to say, "the performance properties of the most widely used implementation of Language X."
English doesn't lend itself well to precision. Therefore, people rely on the ability of others to use contextual clues to infer assumptions.
It's pretty clear in this case what point the parent was trying to convey.
And I'm not sure what youth has to do with any of this.
I am already old enough to have coded Z80 assembly back in the day and I see this mix of languages and implementations mostly around youth wannabe programmers.
Old becomes new when you don't know it.