7.8 MB Of Keys I Allocated Just To Throw Away
A profiler exposed a hidden cost in my code.
My request handler reads tokens from a huge string and sums their weights. The logic worked, but memory didn’t.
Inside a hot loop I allocated 7.8 MB of strings—one new key for every dictionary lookup—then tossed the key immediately.
The culprit was Substring. Each slice created a fresh string object.
200,000 tokens
- Method A (Substring): 23.4 ms, 7,812 KB allocated.
- Method B (Span Lookup): 14.9 ms, 0 KB allocated.
Method B runs 1.5× faster and generates no garbage.
In .NET 9 you can call GetAlternateLookup. Instead of a new string, you pass a ReadOnlySpan<char>, which is just a window onto the original string—no copying.
The dictionary hashes the span directly against existing keys, delivering the same result without the allocation.
Things to remember
- Works with
StringComparer.OrdinalandStringComparer.OrdinalIgnoreCase. - Throws at runtime if you use a custom comparer that lacks alternate lookup support.
- Ideal for hot paths such as parsers, log processors, or CSV scanners.
- Skip it for simple lookups with only a few keys.
I now hunt my code for Substring followed by TryGetValue. That pattern wastes massive amounts of memory.
Source: https://dev.to/ssukhpinder/78-mb-of-keys-i-allocated-just-to-throw-away-50mn
Optional learning community: https://github.com/ssukhpinder/dev-to-code-samples/tree/main/023-dictionary-alternate-lookup
