4 ms·
This article conflates two separate issues: Automatic memory management, and Virtual Machine runtimes. People often make the mistake of thinking that some sort
by jordwalke 11y ago
This article conflates two separate issues: Automatic memory management, and Virtual Machine runtimes. People often make the mistake of thinking that some sort of garbage collection strategy (such as reference counting[1] collection (ARC) or tracing collectors) implies that you must be running in a VM (which typically employ some kind of JIT to achieve reasonable performance). This is not true - see Haskell, OCaml, SML, and Swift (for reference counting collection).
In my experience, many of the issues with debugging performance issues are not related to memory management, but understanding JIT heuristics which are moving targets (especially in the dynamically typed languages).
I think we need to collectively separate the idea of some kind of automated (or semi-automated) collection strategy, from a language level JITed Virtual Machine. You may have one without the other.
[1]https://www.cs.virginia.edu/~cs415/reading/bacon-garbage.pdf https://www.cs.virginia.edu/~cs415/reading/bacon-garbage.pdf
- aidenn0 11y agoI reread the article after seeing your post, and could not find where they made this conflation. I've not worked on performance critical code running under a JIT, but have worked on performance critical code running under a GC, and having an intimate knowledge of memory can be vital to understanding the performance of your application.
- jordwalke 11y agoThe 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