5 ms·
Hard pass on the garbage collector. We don't need that, and the minimal GC support that was in the standard has been removed from C++23.
by felipefar 2y ago
Hard pass on the garbage collector. We don't need that, and the minimal GC support that was in the standard has been removed from C++23.
- pizlonator 2y ago> Hard pass on the garbage collector. Why? > We don't need that You do if you want comprehensive use-after-free protection. > and the minimal GC support that was in the standard has been removed from C++23. Not related to what I'm doing. The support you cite is for users of the language to write garbage collectors "on top" of the language. Fil-C++'s garbage collector is hidden in the implementation's guts, "below" the language. Fil-C++ is compliant to C++ whether C++ says that GC is allowed or not.
- felipefar 2y agoThey solve the use-after-free issue by keeping pointed objects alive, not by helping you think better about object lifetimes in your code. That means some objects will live for longer than you initially thought they would, and potentially even introduce circular references. Added to that, they also introduce random, unpredictable slowdowns in your application to run their algorithms. I'm not yet sold on Rust, but exploring alternatives for achieving memory safety without needing to put on a GC is commendable.
- pizlonator 2y ago> They solve the use-after-free issue by keeping pointed objects alive That's not at all what Fil-C's garbage collector does. If you free() an object in Fil-C, then the capability is marked free and the next GC cycle will: - Delete the object. - Repoint all capabilities that referred to that object to point to the free singleton capability instead. This ensures that: - Freeing an object really does free it, regardless of whether the GC sees it as reachable. - Using an object after freeing it is guaranteed to trap with a Fil-C panic, and that panic is guaranteed to report that the object has been freed so you know why you're trapping. Also, as a bonus, if you don't ever free your objects, then the Fil-C GC will delete them for you once they become unreachable. So, you can write Java-style code in C++, if you want. > That means some objects will live for longer than you initially thought they would, and potentially even introduce circular references. No idea what you mean there. Maybe you're thinking of reference counting, which isn't a form of garbage collection. (Reference counting is different precisely because it cannot handle cycles.) > unpredictable slowdowns in your application to run their algorithms. Fil-C's garbage collector is 100% concurrent. It'll never pause your shit.
- pornel 2y agoFil-C sounds very similar to Google's MiraclePtr. However, Safe C++ (Circle) and Rust do much more than that. They are not limited to pointers on the heap, and the borrowing rules work for all references including the stack. They also work for references that need to be logically short even when the data is not freed, e.g. internal references to data protected by a mutex don't outlive unlocking of the mutex. And all of that is at zero runtime cost, and by guaranteeing the code correctly doesn't create dangling references in the first place, not merely by softening the blow of run-time failures of buggy code.
- pizlonator 2y agoFil-C is nothing like MiraclePtr. Fil-C gives you comprehensive memory safety. Yes, it handles references to the stack. Misuse traps or leads to other safe outcomes. Fil-C makes it so races have memory safe outcomes (like Java). Circle and Rust are strictly less safe than Fil-C, since both have unsafe escape hatches. Fil-C doesn't even have an unsafe escape hatch.
- pornel 2y agoOh, I remember this project now. I see it still advertises 3x-10x overhead. To me this takes it out of being a contender in the systems programming space. This can't be dismissed as a mere quality-of-implementation detail. C and C++ are used because they don't have such overheads, so it takes away the primary reason to use these languages. When non-negligible overhead is not a problem, there are plenty of nicer languages to choose from for writing new code. This leaves Fil-C in a role of a sandbox for legacy code, when there's some unsafe C code that won't be rewritten, but still needs to be contained at any cost. But here you need to compete with WASM and RLBox which have lower-overhead implementations.
- pizlonator 2y agoFil-C was 200x slower when I started and the latest overheads are lower than 2x in a lot of cases. It’s getting faster every month, though I don’t always update the docs to say the latest numbers (because I’m too busy actually making it faster). I think the reason why folks end up using C is often because they have a gigantic amount of C code and for those folks, Fil-C could easily be good enough as is. But dismissing it as a contender because the perf isn’t there today even as it’s getting steadily faster (on a super aggressive trajectory) is a bit unfair, I think.
- jandrewrogers 2y agoGarbage collectors are directly in conflict the requirements of many high-performance software architectures. Some important types of optimization become ineffective. Also, GC overhead remains unacceptably high for many applications; performance-sensitive applications worry about context-switching overhead, and a GC is orders of magnitude worse than that. C++ is usually used when people care about performance, and a GC interferes with that.
- pizlonator 2y agoFil-C uses a concurrent garbage collector that never pauses the program. There is no pause in Fil-C that looks anything like the cost of a context switch. It’s a design that is suitable for real time systems. The GC is similar to what I used here, just much more optimized: http://www.filpizlo.com/papers/pizlo-eurosys2010-fijivm.pdf http://www.filpizlo.com/papers/pizlo-eurosys2010-fijivm.pdf
- jandrewrogers 2y agoThe GC must interrupt the software because otherwise it would have no resources with which to execute. If I am running a standard thread-per-core architecture under full load with tightly scheduled CPU cache locality for maximum throughput, where do you hide the GC and how do you keep it from polluting the CPU cache or creating unnecessary cache coherency traffic? People have made similar claims about Java GCs for years but performance has never been particularly close, which is generally in agreement with what you would expect from theory. A GC will always lack context that the software has.
- pizlonator 2y agoMalloc has its own overheads, and they are often worse than those created by GC. Something to consider is that Fil-C permits you to do all of the things you would normally do, as a C programmer, to reduce or eliminate allocation - like having structs embedded in structs and avoidance of allocation in core algorithms. This makes it quite different from Java or JS where the language forces you to allocate to basically do anything. I think folks conflate “GC overhead” with the overhead of languages that happen to use GC.
- 3836293648 2y agoBecause if you can afford GC you're not using C/++. We need memory safe systems stuff. Higher level memory safety has been solved for decades
- pizlonator 2y agoI don’t buy that at all. If I could use C++ with GC, I would - but I can’t because other than Fil-C++ no GC works soundly with the full C++ language, and those that work at all tend to be unreasonably slow and flaky due to conservatism-in-the-heap (Boehm, I’m looking at you). Reason: GC and memory safety are tightly coupled. GC makes memory safety easy, but GC also requires memory safety to be sound and performant. So there isn’t anything else out there quite like Fil-C++. Only Fil-C++ gives you accurate high perf GC and the full C++ language. Finally, “affording” GC isn’t really a thing. GC performs well when compared head to head against malloc. It’s a time-memory trade off (GC tends to use more memory but also tends to be faster). If you want to convince yourself, just try a simple test where you allocate objects in a loop. Even JS beats C++ at that benchmark, because GCs support higher allocation rates (just make sure to make both the C++ and the JS version complex enough to not trigger either compiler’s escape analysis, since then you’re not measuring the allocator).
- 3836293648 2y ago"affording" GC is absolutely a thing. You're measuring the wrong thing. It's primarily about latency, not throughput, and GC can only go head-to-head on throughput. Secondly you have places where you don't have dynamic memory at all which you're also conveniently ignoring.
- pizlonator 2y agoFil-C has a concurrent GC. It doesn’t stop your program, ever. If your C code doesn’t dynamically allocate then it won’t create any GC load in Fil-C.
- riku_iki 2y ago
- pjmlp 2y agoUnreal C++, C++/CLI, and V8 C++ do need one. It should never have been there in first place, because it ignored their requirements, and thus it was never adopted by them or anyone else.