3 ms·
The article divides programming languages into two groups: Those that require you to manage memory manually and those that rely on language level managed memory
by jordwalke 11y ago
The article divides programming languages into two groups: Those that require you to manage memory manually and those that rely on language level managed memory. However, the examples of the managed memory languages also rely on language level Virtual Machines and/or JITs (which are critical to achieving excellent performance in those respective languages). Then, the article points out that the people using these "garbage collected languages" (which are also JITed (in a VM likely)) tend to have problems debugging performance issues. If he's right, then the examples aren't making the case very convincingly because the realm of languages with garbage collection isn't divided granularly enough in his analysis. The result is attributing the problem to a common language feature that they all share, without acknowledging that they also all share other very important features.
I'd never claim that understanding memory usage/allocation/freeing isn't important. It's important to understand how memory is used whether that be understanding how your collector handles generations of memory in a GC'd language, or whether it be understanding how your programming patterns cause a waterfall of destructor chains in a manually managed language. Often, understanding these things is difficult.
My claim was that, in my experience, the biggest difficulties in debugging performance were in understanding JIT heuristics in language level Virtual Machines. This is because (especially in dynamic languages) the heuristics aren't documented anywhere, they're subject to change, and are likely not consistent between particular runtimes you're hosted within. (Those optimizations you made just for V8, could even hurt perf if you run your library in JSC).
There's also the issue with language level virtual machines in that they usually impose some system wide tax on many operations (a layer of indirection), so I could see the people mentioned in the article having a hard time squeezing out that last portion of performance due to that indirection - again, that might be the fault of there being a language level Virtual Machine - and not necessarily as much related to memory (it depends on your application, and amount you allocate, of course).
In my experience, optimizing collection behavior has been relatively straightforward in comparison and the techniques you learn for one collector seem to translate to others. Perhaps my experience is biased towards JIT/VM/GC in dynamic languages where the JITs are so much more complex in comparison.
I have seen core hot paths in critical client side JS libraries be slowed down 9x because of obscure JIT deopts caused by properties names beginning with a dollar sign. I'm not just talking about a 9x slowdown of field lookups - our entire end to end benchmarks tanked (since fixed). Perhaps the VM architects decided that something with a leading dollar sign would not likely benefit from being made into a hidden JIT class? I've never had anything so obscure happen with any kind of garbage collection, whether that be reference counted ARC, or a tracing collector.
Edit: spelling