Low pause collectors exist explicitly for this purpose. ZGC and Shenandoah both trade throughput (more concurrent collections) for extremely low pause times: https://malloc.se/blog/zgc-jdk16
Does that mean they also trade _memory_ for low pause times? Because, in our application, the memory required for avoiding significant GC pauses is at least 4x the amount of memory we actually need at any given time.
This can be significant too.
Have you measured that with ZGC? Because due to using virtual pointers specifically, ”third-party” tools may report higher virtual memory usage than what it actually uses.
It's all about compromises. Only Rust is uncompromised.