When you're using a programming language that naturally steers you to write slow code you can't only blame the programmer.
I was listening to someone say they write fast code in Java by avoiding allocations with a PoolAllocator that would "cache" small objects with poolAllocator.alloc(), poolAllocator.release(). So just manual memory management with extra steps. At that point why not use a better language for the task?
Java doesn't steer you into object pools. I wrote Java code for 20 years and never used a cache to avoid allocating objects, and never saw a colleague use one. The person you were talking to doesn't know what he's doing.
This point gets raised every single time managed languages and low latency development come up together. The trade off is running "fast" all of the time, even when you don't have to, vs running slow most of the time and tinkering when you need to go fast.
I've spent a fair few years developing lowish (10-20us wire to wire) latency trading systems and the majority of the code does not need to go fast. It's just wasted effort, a debugging headache, and technical debt. So the natural trade off is a bit of pain to make the hot path fast through spans, unsafe code, pre-allocated object pools, etc and in return you get to use a safe and easy programming language everywhere else.
In C# low latency dev is not even that painful, as there are a lot of tools available specifically for this purpose by the runtime.
You might have an application for which speed is not important most of the time. Only one or two processes might require allocation-free code. For such a case, why would you burden all of the other code with the additional complexity? Calling out to a different language then may come with baggage you'd rather avoid.
A project might also grow into these requirements. I can easily imagine that something wasn't problematic for a long time but suddenly emerged as an issue over time. At that point you wouldn't want to migrate the whole codebase to a better language anymore.
> So just manual memory management with extra steps
This is actually the perfect situation: you are allowed to do it carefully and manually for 1% of code on the hot path, but you don't have to worry about it for the 99% of the code that's not.
TBH, I do not see how Java as a language steers anyone to use one those shotguns. E.g. the knowledge about algorithmic complexity is foundational, the StringBuilder is junior-level basic knowledge.
Bad idea. I've made a pool allocator before, but that was for expensive network objects and expensive objects dealing with JNI.
Doing it to avoid memory pressure generally means you simply have a bad algorithm that needs to be tweaked. It's very rarely the right solution.
[dead]
The problem with comments like these is that guessing what "better language" a commentator has in mind is always an exercise left up to the reader. But that tends to be by design—it's great for potshots and punditry, because it means not having make a concrete commitment to anything that might similarly be torn apart in the replies, especially over double standards—like if the "better language" alluded to is C (and it generally is)—the language with a standard library that "steers" you towards quadratic string operations because the default/natural way to refer to a string's length is O(n).