13 ms·
Still not convinced that memory semantics are critical in the vast majority of domains. Incredibly fast speeds can be achieved with simple GC and RC for short-r
by netbioserror 4y ago
Still not convinced that memory semantics are critical in the vast majority of domains. Incredibly fast speeds can be achieved with simple GC and RC for short-running programs, and programs with sustained runtimes can rely on generational GC. These methods have the advantage of nearly eliminating the need for memory semantics, leaving only business logic behind.
The best example might be Nim, which drastically reduces GC pressure over Java or Go by stack allocating and passing immutably by value wherever it can. No gigantic runtime to link against! I've been able to make fast, safe programs so quickly with Nim that it promptly ended my Rust fascination phase. Kernels, realtime software on rockets, and Facebook- or Discord-scale backends seem like good fits for Rust, but I'm not convinced it should be used almost anywhere else. Looking at the sheer volume of memory logic in Zig and Rust, I have to ask: "Why do we continue doing this to ourselves?"
- jackmott42 4y agoYou can get the idea that a GC has minimal impact on performance when you just look at things like how fast the GC runs, or what % of time is spent in GC, but that only represents a portion of performance implications, there are lots of indirect effects: 1. More memory is used, which means more CPU cache evictions happen 2. There will be things the language won't let you do, because it is garbage collected 3. There will be extra FFI costs, like when making OS calls or calling into other languages 4. There will be cultural tendencies, if a language uses GC, the people who designed it and used it are less likely to be interested in compromising other things for extreme performance. Example: If a linq query has overhead in C#, and they have to make a breaking change to eliminate it, they will not. In Rust if an iterator is slower than what hand coded C would be, its a bug, and every effort will be made to fix it if possible. That said, it is still the case that most programs aren't penalized by GC much. But people do still work on operating systems, games, databases, video editing tools and such where getting great performance is really important.
- deleted 4y ago[deleted]
- TylerE 4y agoMalloc isn’t free, either.
- 59nadir 4y ago`malloc` doesn't make up a meaningful percentage of performance-oriented software's execution time. Most of those programs bulk allocate and manage memory internally, so the cost of `malloc` isn't a relevant argument against managing memory manually. Indeed it's entirely possible to write a program that doesn't ever use `malloc` while still using allocations internally, from a stack allocator. The point isn't to `malloc` every single allocation and pair them up with `free` calls; it's to use allocators that alleviate that burden while also allowing you to pick an allocation pattern that makes sense for the use case (and internal use cases). As an example, if your total memory usage for your program could be determined at startup to be 1GB, then you could allocate 1GB up front and allocate from that memory in the rest of the program, guaranteeing that nothing after startup ever goes to the OS for memory. Overall it's much easier to write obviously efficient software in Zig than it is in Rust, IMO, and it's much easier to see at a glance that something won't behave stupidly when it comes to allocation and deallocation. To be fair, this is something Zig has over most other languages as well, so it's not exactly specific to Rust.
- gpderetta 4y agoAnother hidden penalty of some (but not all) GCs is that they can't handle interior pointers so anything that is addressable need to be separately allocated. So not only you have more allocations to track and more space and time overhead, you also add indirections where they are not needed. Of course a Sufficiently Smart Compiler can remove the overhead, but well...
- arc619 4y agoNim uses stack allocated value types by default, and GC (or ptr) is an optional tag to the type definition. GC types use borrow & move analysis like rust (not as good yet tho) so it can elide GC work when possible. GC is also not stop-the-world, deterministic (assuming no cycles), and configurable to soft realtime performance. So you dont need to use the GC, but it will give you RAII if you want without needing to perform the dance of the borrow checker. BTW Nim is also closing in on Rust's borrow checking semantics, too!
- arc619 4y agoAlso, aside from the fact GC is optional in Nim, what are you thinking of that cant be done with a GC?
- elcritch 4y ago> That said, it is still the case that most programs aren't penalized by GC much. But people do still work on operating systems, games, databases, video editing tools and such where getting great performance is really important. This statement simply isn't true though, at least in the general sense. Sure, for old school atomic RC and compilers that didn't do RC elision etc it might've been true. But we can and have made smarter compilers, just like Rust has gotten smart about life times. Like @netbioserror I use Nim, but for embedded and real-time stuff. There is a minimal overhead (one machine word per allocation), but using Nim's ARC "memory management system" gives me results comparable to Zig or Rust though with much less work. Technically ARC without the cycle collector isn't a GC. There's no reason D and other languages with "memory management" couldn't do similar RC based systems. As the compilers get smarter it approaches the same result as Rust's manual lifetime analysis. In many cases compilers can be smarter than human programmers about memory. Even then, there's occasions where in Nim one can and will reach for manual memory allocations. It's easy to do when wanted. > 2. There will be things the language won't let you do, because it is garbage collected There will be things that systems like Rust's lifetimes makes harder / less performant as well: https://ceronman.com/2021/07/22/my-experience-crafting-an-interpreter-with-rust/ https://ceronman.com/2021/07/22/my-experience-crafting-an-in... > 3. There will be extra FFI costs, like when making OS calls or calling into other languages For generational GC's this is true, but for RC systems not as much. > There will be cultural tendencies, if a language uses GC, the people who designed it and used it are less likely to be interested in compromising other things for extreme performance. This is certainly a thing. However, cultures can vary a lot. For example Nim provides zero-cost iterators as well as minimal-cost "closure" iterators. Now Nim's string libraries do a lot of copies by default which makes it easy to ruin performance. However, there's an open RFC to provide CoW strings to reduce this overhead. There's also the new `lent` type too. After all, it's used in games and embedded so there's desire for that. Certainly if your language is tedious about memory management, you'll spend more time on it. Though as an end user I'm not sure I've noticed a practical difference between Go and Rust programs as compared to C#/Java applications. The latter I avoid running if possible because of their general bloat.
- kaba0 4y ago> More memory is used, which means more CPU cache evictions happen The first part is true, and the second part is sort of true, but it may or may not matter. The order of magnitude speedups that good cache usage can cause only happens when you are having a small hot loop working over a huge amount of data that has an easy to guess access pattern (e.g. serial). I am not convinced that your ordinary program would have too many such loops and thus that it would have a huge speed up were it rewritten in C from a managed language. > There will be things the language won't let you do, because it is garbage collected There are always escape hatches > There will be extra FFI costs, like when making OS calls or calling into other languages Do you mean like GC barriers and such? But we do agree on your last paragraph, and sure low-level languages will always be needed. But the niche where they are irreplaceable are very small, if we are pedantic OS and games are also not necessarily to be written in them (see Microsoft’s singularity, the latter has plenty of examples)
- Yoric 4y agoFrankly, my reason for using Rust is not memory semantics (I'd be happy for most applications with a Gc), it's the type system. I could be writing in Haskell for an even more powerful type system, of course, (especially now that Haskell has gained linear types) but the language never took hold outside of academia.
- kaba0 4y agoWell, “never took hold” is relatively. It is and will likely always be a niche language, but one with a quite big audience and ecosystem. There are people happily using different languages that are much smaller, they just happen to occupy a less academic niche — e.g. I’m guessing but you probably don’t have such feelings against D, when it might very well be smaller than Haskell.
- Yoric 4y agoTo clarify, I have actually coded a bit in Haskell and I have actually released open-source code in SML/NJ, a commercial application in OCaml and worked (as a very minor contributor) on industrial code in Coq. But if I have to start a new industrial project, I will most likely use Rust, because it is easier to hire and because there is lots of momentum in the Rust ecosystem, which means that there are crates for just about everything.
- ben0x539 4y agoI know this is facile, and it's speaking as someone with a lot more enthusiasm about than expertise with Haskell, but whenever I write some toy Haskell code and have to think about "remember to close this file handle before the end of this block" or "make sure not to use this file handle outside this block (because we just used a combinator to close it)", I'm baffled that Rust has mostly figured out that whole class of problem before Haskell
- deleted 4y ago[deleted]
- deleted 4y ago[deleted]
- klyrs 4y ago> Still not convinced that memory semantics are critical in the vast majority of domains. This is okay. Zig is not targeting the vast majority of domains. It targets the low-level, performance-critical domain that C occupies. It would be a great language to write a compiler/interpreter for a higher-level language that has the bells and whistles that you want.
- netbioserror 4y agoIt's still bizarre though that Rust is capturing such ridiculous mindshare. I suspect it has a lot to do with web developers being plugged into Mozilla, and Mozilla spending quite a lot on Rust development and marketing. And Zig may be being roped into it. It seems to be a temporary low-level programming zeitgeist driven by YouTube and Reddit recommendation algorithms to an audience that has never done it and probably never will.
- j-james 4y agoWhile I love Nim, another reason for Rust's success (aside from its type system, general good language design, and zero-cost memory safety) is that the tooling is ridiculously good, probably the best of any language I've used, sans maybe Java. Nim's tooling is improving but still has a ways to go - I still occasionally get orphaned langserver processes, and while the langserver itself is pretty good, it's nowhere near the level of what rust-analyzer can do. Especially with error messages and (automatic) refactoring.
- wyldfire 4y ago> It's still bizarre though that Rust is capturing such ridiculous mindshare. I don't think it's that bizarre. The two big headline features that bring Rust such popularity are: #1 "70% of bugs are memory-safety bugs" [1] and Rust can help solve those, and #2 C/C++ have a couple of package manager solutions - none of which have critical mass and Rust "comes with" cargo. Those two make me really eager to continue experimenting with Rust. > It seems to be a temporary low-level programming zeitgeist driven by YouTube and Reddit recommendation algorithms to an audience that has never done it and probably never will. This is some weird gatekeep-y kinda thing. Most of us didn't start out with low-level programming. Wouldn't it have been odd and frustrating for someone to tell your younger self that you have "never written C and probably never will"? [1] https://github.com/microsoft/MSRC-Security-Research https://github.com/microsoft/MSRC-Security-Research
- DeathArrow 4y agoThe good thing about Nim is that you can chose between several garbage collection algorithms, use no garbage collector at all and do manual memory management or allocate without freeing if the program is short lived and doesn't use much memory. Also having a C interface is great since you can use any C library.
- Tarq0n 4y agoHow different are these options from each other, syntactically and semantically? Do i need to know all of them to read library code?
- sramsay 4y agoI completely agree with what you're saying here and wonder every day why Nim hasn't taken over the world. People seem not to realize that Nim not only has a "pluggable" gc system (so you can pick the gc that makes sense for your use case), but also allows you to turn the gc off. As in, no gc (which is exactly what you need in certain very narrow situations).
- deleted 4y ago[deleted]
- netbioserror 4y agoOne of these days I'll be able to try embedded Nim with no GC. I want to see what its arena allocation semantics are like.
- Decabytes 4y agoThe thing that turns me off to Nim is the issue with it getting picked up as malware. I can't even download the installer for the language without it getting removed from my computer after getting picked up by Windows Defender It's not Nims fault, but is still a point of friction
- ibiza 4y agoThat's a a compelling argument: GC/RC w/ stack allocation where possible. I associate GC w/ pointer chasing and the unavoidable L1, L2, L3 cache trashing that goes w/ it. To what extent is this possible? Does Nim have LTOs that rewrite memory handling across compilation units? I'm guessing no, and instead it's local & one-off, rather than something one can bank on.
- netbioserror 4y agohttps://zevv.nl/nim-memory/ https://zevv.nl/nim-memory/ Local variables (also called automatic variables) are the default method by which Nim stores your variables and data. Nim will reserve space for your variable on the stack, and it will stay there as long as it is in scope. In practice, this means that the variable will exist as long as the function in which it is declared does not return. As soon as the function returns the stack unwinds and the variables are gone. In Nim, all your data is stored on the stack, unless you explicitly request it to go on the heap. Strings and seqs are allocated on the heap and accessed via a stack pointer, but the stack pointer controls their lifetimes, and semantically behaves like any other local variable.
- j-james 4y agoDo note that this was written before Nim's new runtime, ARC/ORC, became stable! The author has been working on a companion guide to the new runtime that goes over how it manages to be efficient with reference counting, but it's (very) much a work in progress.
- arc619 4y ago> That's a a compelling argument: GC/RC w/ stack allocation where possible. Indeed, it's a great combination that means you're productive and performant without really trying most of the time. The type system is really good as well, and in general there's a strong focus on compile time over run time like Zig, but with better procedural macros than Rust. > To what extent is this possible? Does Nim have LTOs that rewrite memory handling across compilation units? The GC is built on general move analysis with destructors you can hook for your own types. The nice thing is it's a deterministic, compile time expansion (you can view with '--expandArc:somefunction'), so it's useful for embedded or high performance stuff. The intro to ARC is pretty good for an overview: https://nim-lang.org/blog/2020/10/15/introduction-to-arc-orc-in-nim.html https://nim-lang.org/blog/2020/10/15/introduction-to-arc-orc...
- pornel 4y agoThey are not for majority of programs, but they are essential in the niches that Rust and Zig target. This is why it took so long to have a viable alternative to C and C++. Every other language decided "memory management is hard, GC is fine for 99% of programs, let's go with GC", and language after language kept disqualifying itself from the no-GC niche. From the Rust intro talk: http://venge.net/graydon/talks/intro-talk-2.pdf http://venge.net/graydon/talks/intro-talk-2.pdf > • Everyone is dodging the niche I'm interested in.
- netbioserror 4y agoA great point. As I’ve commented before though, watching webdevs get excited for it, or “rewrite it in Rust,” or developers contort it to try and do things it shouldn’t is sort of morbid from a distance. I’m sure Darwin will work his magic and Rust will settle in the intended niche. But seeing the insane excitement levels and recruiters using Rust to attract applicants…like I said, morbid, and hard to sustain.
- pornel 4y agoRust has features besides memory safety that are generally useful — robust error handling, pattern matching, fast and powerful JSON support, nice package manager, ease of deployment, first-class WASM support, etc. Some people value these features enough to use Rust even outside of its niche. Even when performance isn't critical, it may be a nice to have. I sometimes feel like Rust is overcompensating for its hard parts :) It's not easy to learn its memory management, but the error messages do their best to teach you!
- randyrand 4y agoThere a lots of good languages to choose from with GC. Zig would not have much unique to offer if it was a GC language, imo.