Span<T> & Memory<T>
Call `text.Substring(16)` inside a parsing loop and every iteration quietly allocates a brand-new string on the heap and copies characters into it, yet there is a way to read those exact same characters with zero new allocations at all.
- ▸
Substringon"Content-Length: 132"allocates and copies a new string; a window over the original characters costs nothing. - ▸One value type wraps a heap array, a stack buffer, and native memory alike, and one signature serves all three.
- ▸The compiler refuses to let that view become a field or cross an
await: its pointer dies with the frame.
A header line arrives as the text "Content-Length: 132", and you want the 132 sitting after the colon. The obvious move:
string line = "Content-Length: 132"; string number = line.Substring(16); // "132" int length = int.Parse(number);
Substring looks free. It is not. Each call allocates a brand-new string object on the heap and copies the selected characters into it: one allocation plus an O(n) copy, every single time you call it.
One header is nothing. But a server reading thousands of request lines a second, splitting each into fields, runs that allocate-and-copy on a hot path. The small short-lived strings pile up faster than you would guess, and the collector then has to walk and reclaim every one of them. That is collection pressure you manufactured purely to look at characters that were already in memory.
The characters you actually want already exist, contiguous, inside line. The waste is building a second copy of them only to read them and throw the copy away. The rest of this topic is about reading them where they already sit, without the copy and without the allocation.