Go, don't collect my garbage
If you make something that is performance critical, and in particular if it's concurrent, the normal rule is you avoid allocating on the heap at all. Use object preallocated data (just operate on massive lists), or use pools of data etc.<p>Any language/runtime will support just allocating a large blob of data and then playing with it with code that looks like C.  
Effectively once you want to write perf sensitive code in a garbage collectied language you have to <i>stop</i> writing idiomatic code for that language.<p>That can mean using data orientation (SoA for example is a very non-idiomatic thing to do in most C-like languages and especially OO ones). Not using heap allocation at all for any length of time is definitely non-idiomatic in Java/C#/Python/js etc., but that's what you need to do if you want any kind of performance.<p>There are two truths here: 1) Any language can be as fast as C and 2) When they are as fast as C, they also look like C regardless what it was to begin with.