I had a loop that did something embarrassingly simple: fold a stream of feature vectors into one running total. Add a vector, add the next, keep going. A few hundred thousand of them. The math is a for-loop over some doubles, nothing that should trouble the garbage collector.
The allocation profile said otherwise. Gigabytes. For adding numbers.
I knew why the second I looked at the operator. I'd written + the tidy, immutable way years ago and never thought about it again:
public static Vec operator +( Vec a , Vec b ) { var result = new double [ a . Data . Length ]; for ( int i = 0 ; i < result . Length ; i ++) result [ i ] = a . Data [ i ] + b . Data [ i ]; return new Vec ( result ); }
Enter fullscreen mode
Exit fullscreen mode
That's a perfectly reasonable operator. Every call hands back a brand new Vec with its own fresh array, nobody's state gets stomped, and you can reason about it without fear. It's also a fresh 8 KB array on the heap every single time you add two 1024-dimension vectors.…