Unexpected Optimization #0: at() vs operator
Writing a soft synth requires a lot of optimization. As I develop twytch and the synth engine it’s built on, mopo, I’ll be posting many of the optimizations I make, especially nonobvious ones. These could range from simple things like using one-multiply instead of two-multiply interpolation:
Or could be uglier solutions like embedding assembly instructions in C++. I’m not a C++ optimization expert yet, so some of these things may be more obvious than others.
This first unexpected optimization concerns accessing values from std::vector. Consider these two methods of element access:
There is a significant difference between the two: at() does boundary checking while operator does not. You don’t normally notice this performance difference, but I was running it once per audio sample for every single component which totaled in the millions per second.
Now why would I use at() instead of operator in the first place? The way mopo sets up polyphony is that all the module instances in each voice share a list of input pointers. For example, every Filter instance in each poice has a pointer to the same std::vector. Using at() on a pointer to std::vector is much easier to read than using operator or dereferencing first so I first chose the slower but prettier method.
Fortunately switching from at() to operator an easy thing to fix, and I got a significant 25% speed boost because of it.