5 ms·
Level 1 systems programmer: "wow, it feels so nice having control over my memory and getting out from under the thumb of a garbage collector" Level 2 systems p
by kibwen 2y ago
Level 1 systems programmer: "wow, it feels so nice having control over my memory and getting out from under the thumb of a garbage collector"
Level 2 systems programmer: "oh no, my memory allocator is a garbage collector"
- seanthemon 2y agoAt the very bottom of everything is a garbage collector..
- amelius 2y agoLevel 3 system programmer: "get me out of this straight jacket and give me my garbage collector back so I can get stuff done"
- forrestthewoods 2y agoNo. Just no. For as painful as the debugging story was I have spent vastly more amounts of time working around garbage collectors to ship performant code.
- 0x457 2y agoWhat, you don't like doing GC only N requests (ruby web servers), disabling GC completely during working hours (java stock trading), fake allocating large buffers (go's allocate and don't use trick)?
- pton_xd 2y agoAin't nothin' wrong with configuring V8 to have unbounded heap growth, disabling the memory reducer, and then killing the process after a while.
- mike_hearn 2y agoThe Java shops you're thinking of didn't disable GC during working hours, they just sized the generations to avoid a collection given their normal allocation rates. But there were / are also plenty of trading shops that paid Azul for their pauseless C4 GC. Nowadays there's also ZGC and Shenandoah, so if you want to both allocate a lot and also not have pauses, that tech is no longer expensive.
- 0x457 2y ago> The Java shops you're thinking of didn't disable GC during working hours, they just sized the generations to avoid a collection given their normal allocation rates. Well, I just trivialized it. However, in one case in mid 00s, I saw it disabled completely to avoid any pauses during trading hours.
- wpollock 2y agoUsed to do this in C decades ago. Worked on Unix but I doubt it works on Linux today, unless you disable memory overcommit completely.
- neonsunset 2y agoI'd wager it was an issue with the language of choice (or its GC) being rather poorly made performance-wise or a design that does not respect how GC works in the first place :)
- forrestthewoods 2y agoI’m sure you would! GC is like communism. Always some excuse as to why GC isn’t to blame. > or a design that does not respect how GC works in the first place It’s called shipping a 90 Hz VR game without dropping frames.
- neonsunset 2y agoAside from finding the analogy strange and unfortunate, I assume you're talking about Unity, is that correct? (if that is the case, I understand where the GC PTSD comes from)
- o11c 2y ago> I’m sure you would! GC is like communism. Always some excuse as to why GC isn’t to blame. To be fair, there are about 4 completely independent bad decisions that tend to be made together in a given language. GC is just one of them, and not necessarily the worst (possibly the least bad, even). The decisions, in rough order of importance according to some guy on the Internet: 1. The static-vs-dynamic axis. This is not a binary decision, things like "functions tend to accept interfaces rather than concrete types" and "all methods are virtual unless marked final" still penalize you even if you appear to have static types. C++'s "static duck typing" in templates theoretically counts here, but damages programmer sanity rather than runtime performance. Expressivity of the type system (higher-kinded types, generics) also matters. Thus Java-like languages don't actually do particularly great here. 2. The AOT-vs-JIT axis. Again, this is not a binary decision, nor is it fully independent of other axes - in particular, dynamic languages with optimistic tracing JITs are worse than Java-style JITs. A notable compromise is "cached JIT" aka "AOT at startup" (in particular, this deals with -march=native), though this can fail badly in "rebuild the container every startup" workflows. Theoretically some degree of runtime JIT can help too since PGO is hard, but it's usually lost in the noise. Note that if your language understands what "relocations" are you can win a lot. Java-like languages can lose badly for some workflows (e.g. tools intended to be launched from bash interactively) here, but other workflows can ignore this. 3. The inline-vs-indirect-object axis - that is, are all objects (effectively) forced to be separate allocations, or can they be subobjects (value types)? If local variables can avoid allocation that only counts for a little bit. Java loses very badly here outside of purely numerical code (Project Valhalla has been promising a solution for a decade now, and given their unwieldy proposals it's not clear they actually understand the problem), but C# is tolerable, though still far behind C++ (note the "fat shared" implications with #4). In other words - yes, usually the problem isn't the GC, it's the fact that the language forces you to generate garbage in the first place. 4. The intended-vs-uncontrollable-memory-ownership axis. GC-by-default is an automatic loss here; the bare minimum is to support the widely-intended (unique, shared, weak, borrowed) quartet without much programmer overhead (barring the bug below, you can write unique-like logic by hand, and implement the others in terms of it; particularly, many languages have poor support for weak), but I have a much bigger list [1] and some require language support to implement. try-with-resources (= Python-style with) is worth a little here but nowhere near enough to count as a win; try-finally is assumed even in the worst case but worth nothing due to being very ugly. Note that many languages are unavoidably buggy if they allow an exception to occur between the construction of an object and its assignment to a variable; the only way to avoid this is to write extensions in native code. [1] https://gist.github.com/o11c/dee52f11428b3d70914c4ed5652d43f7 https://gist.github.com/o11c/dee52f11428b3d70914c4ed5652d43f... - a list of intended memory ownership policies. Generalized GC has never found a theoretical use; it only shows up as a workaround.
- gnuvince 2y agoI need to find a pithy way to express "we use a garbage collector to avoid doing manual memory management because that'd require too much effort; but since the GC causes performance problems in production, we have spent more effort and energy working around those issues and creating bespoke tooling to mitigate them than the manual memory management we were trying to avoid in the first place would've required."
- ComputerGuru 2y agoThat's not how system programmers think..
- amelius 2y agoA new generation of system programmers is tired of solving the same old boring memory riddles over and over again and no borrow checker is going to help them because it only brings new riddles.
- __s 2y agogc replaces riddles with punchlines
- troutwine 2y agoI agree. If we were to try and pin a thought process to an additional level of systems programmer it’d involve writing an allocator that’s custom to your domain. The problem with garbage collection for the systems’ case is you’re opting into a set of undefined and uncontrolled runtime behavior which is okay until it catastrophically isn’t. An allocator is the same but with less surface area and you can swap it at need.
- amelius 2y agoMeanwhile an OS uses the filesystem for just about everything and it is also a garbage collected system ... Why should memory be different?
- troutwine 2y agoI'm not tracking how your question follows. If by garbage collection you mean a system in which resources are cleaned up at or after the moment they are marked as no longer being necessary then, sure, I guess I can see a thread here, although I think it a thin connection. The conversation up-thread is about runtime garbage collectors which are a mechanism with more semantic properties than this expansive definition implies and possessing an internal complexity that is opaque to the user. An allocator does have the more expensive definition I think you might be operating with, as does a filesystem, but it's the opacity and intrinsic binding to a specific runtime GC that makes it a challenging tool for systems programming. Go for instance bills itself as a systems language and that's true for domains where bounded, predictable memory consumption / CPU trade-offs are not necessary _because_ the runtime GC is bundled and non-negotiable. Its behavior also shifts with releases. A systems program relying on an allocator alone can choose to ignore the allocator until it's a problem and swap the implementation out for one -- perhaps custom made -- that tailors to the domain.
- matklad 2y agoThe answer is clear: just don’t have a malloc implementation in your process' address space!
- poikroequ 2y agoA bump allocator is all anyone really needs
- thebruce87m 2y agoWelcome to embedded! It’s no heaps of fun!
- hinkley 2y ago> no heaps Angry upvote
- eschneider 2y agoI'm always surprised how much I don't miss dynamic allocation. :)
- ckocagil 2y ago"stackoverflow please help me how do i fix memory fragmentation"