On Thu, Jan 14, 2021 at 12:36:12PM +0000, claptrap via Digitalmars-d-learn wrote: [...] > I think you also have to consider that the GC you get with D is not > state of the art, and if the opinions expressed on the newsgroup are > accurate, it's not likely to get any better. So while you can find > examples of high performance applications, AAA games, or whatever that > use GC, I doubt any of them would be feasible with Ds GC. And given > the design choices D has made as a language, a high performance GC is > not really possible.
To be fair, the GC *has* improved over the years. Just not as quickly as people would like, but it *has* improved. > So the GC is actually a poor fit for D as a language. It's like a > convertible car with a roof that is only safe up to 50 mph, go over > that and its likely to be torn off. So if you want to drive fast you > have to put the roof down. How much D code have you actually written and optimized? That analogy is inaccurate. IME, performance issues caused by the GC are generally localized, and easy to fix by replacing that small part of the code with a bit of manual memory management (you *can* rewrite a function not to use the GC; this isn't the Java straitjacket, y'know!), or standard GC optimization techniques like reducing GC load in hot loops. There's also GC.stop and GC.collect for those times when you want more control over exactly when collection pauses happen. I wrote a compute-intensive program once, and after some profiling revealed the GC being a bottleneck, I: (1) Refactored one function called from an inner loop to reuse a buffer instead of allocating a new one each time, thus eliminating a large amoun of garbage from small allocations; (2) Used GC.stop and scheduled my own GC.collect with slightly reduced frequency. The result was about 40-50% reduction in runtime, which is close to about a 2x speedup. Now, you'll argue that had I written this code without a GC in the first place I wouldn't have needed to do all this. However: (a) Because I *had* the GC, I could write this code in about 1/5 of the time it would've taken me to write it in C++; (b) The optimization involved only changing a couple of lines of code in 2-3 functions -- a couple of days' work at most -- as opposed to blindly optimizing *every* single danged line of code, 95% of which wouldn't even have had any noticeable effect because they *are not the bottleneck*; (c) The parts of the code that aren't in the hot path can still freely take advantage of the GC require minimal effort to write, and be free of the time-consuming bugs that often creep into code that manually manages memory. As I said, it's an ROI question. I *could* have spent 5x the amount of time and effort to write the perfect, GC-less, macho-hacker-style code, and get maybe about a 1-2% performance improvement. But why would I? It takes 5x less effort to write GC code, and requires only a couple more days of effort to fix GC-related performance issues, vs. 5x the development effort to write the entire program GC-less, and who knows how much longer after that to debug obscure pointer bugs. Life is too short to be squandered chasing down the 1000th double-free and the 20,000th dangling pointer in my life. A lot of naysayers keep repeating GC performance issues as if it's a black-and-white, all-or-nothing question. It's not. You *can* write high-performance programs even with D's supposedly lousy GC -- just profile the darned thing, and refactor the hotspots to reduce GC load or avoid the GC. *In those parts of the code that actually matter*. You don't have to do this for the *entire* lousy program. The non-hot parts of the code can still GC away like there's no tomorrow, and your customers would hardly notice a difference. This isn't Java where you have no choice but to use the GC everywhere. Another example: one day I had some spare time, and wrote fastcsv (http://github.com/quickfur/fastcsv). It's an order of magnitude faster than std.csv, *and it uses the evil GC*. I just applied the same technique: write it with GC, then profile to find the bottlenecks. The first round of profiling showed that there tend to be a lot of small allocations, which create lots of garbage, which means slow collection cycles. The solution? Use a linear buffer instead of individual allocations for field/row data, and use slices where possible instead of copying the data. By reducing GC load and minimizing copying, I got huge boosts in performance -- without throwing out the GC with the bathwater. (And note: it's *because* I can rely on the GC that I can use slices so freely; if I had to use RC or manage this stuff manually, it'd take 5x longer to write and would involve copying data all over the place, which means it'd probably lose out in overall performance.) But then again, it's futile to argue with people who have already made up their minds about the GC, so meh. Let the bystanders judge for themselves. I'll shut up now. *shrug* T -- Study gravitation, it's a field with a lot of potential.