8 ms·
I like faster latency as much as the next person, but these improvements aren't free. On my own servers I notice approximately 20% of CPU time spent in GC.
by morecoffee 10y ago
I like faster latency as much as the next person, but these improvements aren't free. On my own servers I notice approximately 20% of CPU time spent in GC.
- jemfinch 10y agoI'm a C++ programmer who hates garbage collection on general principle, but I have to say: 20% of CPU time spent in memory management isn't all that unusual (especially in software that hasn't been optimized), whether or not that memory management is automatic garbage collection or manual.
- foota 10y agoIt drastically changed my perspective on gc when I realized that it's really not much slower, it just batches the slowness.
- btmorex 10y agoThat's true for GC vs. manual heap-based memory management, but most GC languages don't do stack allocation at all or only for primitive types and stack allocation is much, much faster than any sort of heap-based memory management.
- foota 10y agoThat's fair. Does Go do this? Or any other somewhat mainstream language? Any thoughts on how arenas (rust) compare to gc and manual allocation for speed?
- kasey_junk 10y agoC# & Go both have stack allocation options. The JVM is supposedly getting them sometime soon.
- CyberDildonics 10y agostack allocation: 20 years in the making.
- weberc2 10y agoI'm of the impression that Java has done escape analysis for a while now. They just haven't had value types, which as I understand, just introduce a semantic for stack allocation.
- pjmlp 10y agoActually I have seen presentations that mentioned Graal is much better at it than Hotspot.
- yxhuvud 10y agoMalloc is O(n²) so it totally depend on how able you are to not do gradual allocation.
- pjmlp 10y agoCheck my other comment https://news.ycombinator.com/item?id=12823102 https://news.ycombinator.com/item?id=12823102
- buzzybee 10y agoArenas trade some granularity and flexibility for speed and fragmentation-free allocation; they're a great choice for bulk data that you can precompute the size of and want to iterate over very quickly, and they're also easy to reason about. You can do many tasks using only arenas and stack allocations, and it'll zip along very quickly. If needed, you can flag liveness to get very efficient reuse of short-lived objects. They're less ideal if you are gradually adding more data over time, and you want to retain a consistently low usage, since you end up with "stairsteps" of latency when it copies into a bigger buffer, and once you have the big buffer, it's quite complicated to shrink it down again. malloc()-style allocation gives you precision over how much you want, and this is most interesting to a memory-constrained system trying to allocate amongst many different processes(the original Unix use-case). But willy-nilly use of malloc() and free() leaves you with lots of fragmentation, as well as a larger attack surface for memory errors. What the actual allocation algorithm does is out of your hands, too, at least if you're depending on the OS allocator(you can always go write your own and supply it with a giant heap to munch on, and this may occur when you need tuning for individual allocation scenarios). In the right scenario, a GC won't do too much differently from a manual allocator(there are lots of optimizations that could bring the allocation to same-or-negligible runtime), but as we all know, right scenarios are something you can't always count on. A GC does, however, greatly simplify the memory management of a long-lived process since it can do nifty things like automatically compact the heap. IME, a mix of stack, GC, and some arenas in the form of growable arrays, is absolutely fine for the needs of most applications. Quite often this last requirement creates a sticking point, though, where the language disallows value semantics for arrays of objects, and then you can no longer assume they're allocated linearly, plus the GC is taxed with additional references to trace. In those cases, if I have them I use arrays of primitive values as crude containers for an equivalent optimization. Either way, it's very annoying and creates some awful code, because those huge batches that I'd like to put in arenas also tend to be the bottleneck for the GC.
- kasey_junk 10y ago> stack allocation is much, much faster than any sort of heap-based memory management. Is that true? I thought nursery allocation was usually as fast if not faster than stack allocations.
- johncolanduoni 10y agoThe allocation speed will be close; a bit worse since the pointer to the end of the current allocation buffer usually isn't in a register and a function call and range check is required. However the overall cost of handling that memory from start to finish is significantly higher than the stack even if it gets clobbered in the first nursery collection. Not because it is very high, but because stack allocation/deallocation is so very simple.
- klodolph 10y agoRange checks can be done by the MMU, they're basically free.
- deleted 10y ago[deleted]
- pjmlp 10y agoAll these GC languages (RC is GC, just in case) do allow stack allocations for any user defined type. Mesa/Cedar, Modula-2+, Modula-3, Oberon, Oberon-2, Active Oberon, Component Pascal, Eiffel, D, Swift
- CyberDildonics 10y agoThe unfortunate part is finding good IDEs with solid debuggers and auto-completion.
- pjmlp 10y agoYes, but that is not relevant for those that live on VI and Emacs.
- weberc2 10y agoGo has excellent auto-completion support, even for vim. It's debugger (delve) is also decent, though not graphical. There are not many languages with better tooling than Go, in my experience.
- NateDad 10y agoFYI, delve is integrated into a lot of editors, and basically works exactly like visual studio when used in VS Code (I used visual studio for C++ & C# for 13 years before moving to Go).
- Dylan16807 10y agoListing largely-obscure languages and repeating them multiple times doesn't do much against a claim of "most".
- weberc2 10y agoJava, Go, and C# all do stack allocation either implicitly via escape analysis (Java), explicitly via value types (C#), or both (Go). I don't know that this is "most" (perhaps by marketshare), but these are certainly 3 of the most popular languages in this space.
- sz4kerto 10y agoIn Java, heap allocation is a single instruction, most of the time.
- PDoyle 10y ago"stack allocation is much, much faster than any sort of heap-based memory management" No, it's not. For short-lived objects, at least on the JVM, allocation is a pointer bump, and collection is free, because unreachable objects are not even walked. Stack allocation doesn't beat that by much.
- jblow 10y agoIt's not unusual in completely terrible code. The difference is if the memory management is manual, you have the ability to clean it up and reduce that overhead toward 0%. If it's a system-enforced GC, you are limited in what you can do.
- kasey_junk 10y agoIn the code I write where it matters the issue is allocation & deallocation time. Thus you don't do those things on the hot path in either gc'd or manual memory management environments. Given that the overhead become 0 in either. Is it sometimes harder to write zero alloc code in GC'd languages? Sure but its not impossible. In Java for instance the difference in performance compared to C++ comes from memory layout ability not memory management.
- pjmlp 10y ago> In Java for instance the difference in performance compared to C++ comes from memory layout ability not memory management. We need more modern languages with AOT compilation, ability to allocate on the stack and use value types. I like C++ and have spent quite a few years using it, before settling on memory safe languages for my work. Many C++ presentations seem to forget on purpose that there are memory safe programming languages, which offer similar capabilities for controlling memory layouts, thus presenting the language as the only capable of doing it. Modula-3 is an example, or Swift and D for something more actual.
- CyberDildonics 10y agoThe reality is that there aren't any straight replacements though since C++ has such mature tools, move semantics take away significant amounts of memory management pain, D without a gc is still exotic, and rust is still in its early stages.
- pjmlp 10y agoIt is a matter of which market is relevant for a developer. There are many use cases where C++ is still used where the use case at hand actually didn't any a real need for it. For example, on my area of work, C++ has been out of the picture since around 2006. We only use it when Java or .NET need an helping hand, which happens very seldom. On the mobile OSes for example, C++ is only relevant as possible language to write portable code across platforms, but not so much for those that decide to focus on just one. There Swift, Java and C# are much better options. For those in HPC, languages like Chapel and X10 are gaining adepts. Also as an C++ early adopter (1993) I remember being told by C developers something similar to what you are saying in regards to tool maturity. Now around 30 years later, their compilers are written in C++.
- johncolanduoni 10y agoThe tradeoff here seems to be a more complicated write barrier, so the loss in performance here will for the most part not show up as time spent in the GC. I'm curious to see how big of an issue this will be; the only GC I've heard of with such a heavy write barrier is OCaml's, which is ameliorated by the language's disposition towards immutability.
- pcwalton 10y agoAnd OCaml has a generational GC, unlike Go. So Go's throughput is going to be hit even harder. Not going with a generational GC is a choice that runs against what has been accepted practice for decades. It may of course work out, but it's what I'd consider an experiment.
- fpoling 10y agoTypical Go code does not generate a lot of short-lived objects, compared with, say, Java or with typical usage of persistent data structures in functional languages. That removes the practical need for generational GC.
- weberc2 10y agoI'm also of the impression that Go's "transactional GC" is similar to a generational GC?
- 10y ago
- sudhirj 10y agoThat might imply that most allocations are happening on the heap - if your code is structured to make allocations only on the stack as much as possible, there wouldn't be that much work to do.