Zero-Allocation Patterns in C# for Low Latency
The GC Problem in HFT
In High-Frequency Trading, the Garbage Collector (GC) is the enemy. A “stop-the-world” Gen2 collection can pause your application for milliseconds—an eternity in the HFT world.
VisualHFT uses strict Zero-Allocation principles in its hot paths to ensure consistent, jitter-free performance.
1. Object Pooling
Instead of creating new objects for every market data update, we use CustomObjectPool<T>.
// ❌ BAD: Allocating per update
public void OnUpdate(Data d) {
var update = new MarketUpdate(d); // GC Pressure!
Process(update);
}
// ✅ GOOD: Pooling
public void OnUpdate(Data d) {
var update = _pool.Get();
update.CopyFrom(d);
try {
Process(update);
} finally {
_pool.Return(update);
}
}
2. Using Span<T> and Memory<T>
We avoid List<T> and array copying in critical loops. Span<T> allows us to slice and process memory buffers without allocation.
3. Structs vs Classes
For small, short-lived data containers (like BookItem), we use readonly struct passed by reference (ref or in) to avoid heap allocations entirely.
Results
By strictly adhering to these patterns, VisualHFT maintains a steady state of 0 bytes allocated per market tick, even during bursts of 100,000 updates per second.