| ▲ | stmw 2 days ago | |
It is fair that there are many ways to be slow in any number of programming languages. I'm surprised to hear "Rust programs spending 30% of their CPU on memory management even when they're as small as a couple hundreds of thousands of LOC", although I can visualize some unique workloads where that's unavoidable irrespective of language & runtime. | ||
| ▲ | pron 2 days ago | parent [-] | |
You say unavoidable, but moving collectors are designed to reduce CPU at high allocation rates by increasing the heap size. Generational moving collectors have a pathological case - a high allocation rate of long-lived objects - but that's quite hard to get yourself into by accident. Their main downside (besides the inherent increased footprint) used to be unpredictable long pauses, which could have a very high impact on tail latencies, and that's just gone with ZGC. Generational moving collectors are a very powerful memory management optimisation, but because they necessarily require some "interesting" FFI layer between the ordinary heap and any passing of pointers between the program and the hardware/OS - the very thing low-level languages are designed not to have - this is a powerful, general optimisation (not perfect, but extremely useful in a wide class of programs) that is not available to low-level programming languages. And it's not the only one, BTW. JIT compilers are also designed for "global" average-case optimisations at the cost of precise low-level control over the worst case, which is another thing that low-level languages trade away. In the most simplistic way, I would say that the precise control that low-level languages are all about helps their performance when programs are small (and can be manually optimised globally) and hurts their performance as programs get large. They have to give up on some optimisations that come at the cost of ceding low-level control, and that includes moving collectors. | ||