So, there is this fairly trivial piece of code that had been bugging me for quite some time, and that I wen't back and forth between a rather black and white implementation and just couldn't find a balance that pleased me, until now. I want to share this insignificant little problem with everyone and solicit some feedback regarding this approach.
The Problem:
So I have my own math library that I've written in c, and within it there is this one particular axis rotation function that gets invoked in my 3D game engine quite often. (This piece of code is essentially the Rodrigues' rotation implemntation, and it involves vectors.) The two implementations of this particular function are as follows.
- void v3rot( vec3 v, const vec3 axis, float radians ); //compute cosine & sine values for the given radians every time
- void v3rot( vec3 v, const vec3 axis, float cosine, float sine ) //cosine and sine values are computed outside of the call
Usually, when this axis rotation function is invoked, it is called 3 times, once for each of the bases vectors x, y, z; The faster of the two implementation (2nd one) involves me defining float variables and calculating the sine and cosine values once in my my caller routine before invoking this function. However, this clutters my code more than I care for, as I would like my code to be more legible. With the solower implementation ( the first one), my code is less cluttered, and I don't have to track additional variables, but I am having to invoke the math function cosf() and sinf() 3 more times than normal, in mose cases:
My Solution:
Cache it. Create a function within my library called "get_sin_cos_cache( float radians, float *cos_val, float *sin_val )", which keeps a running a table of the last 4 or 8 calls to cosf() and sinf(), check against the existing table of stored cosine, sine and radian values, before calculating and updating these tables. So, I continue to use the first implementation in my code and avoid the ugly clutter, but under the hood, in my v3rot() function, i call the get_sin_cos_cache() routine to only calculate sin/cosine values when I need too.
Sauce:
Conclusion:
After crunching some numbers, I calculated that my cache hit was approximately 70%, so I'm thinking about keeping this example in my code for now (if not for the performance gain, then at the very least as a reminder).
I know some (most) of you are thinking "...and? is that it?", and I get it, this is a very trivial example (some may even argue that the gains are not non-existent), but I feel like it serves as one example (good or bad) of how to code with a particular mindset, expressing awareness of what is exactly is going on in your code, not always keeping a back and white approach to what you are doing, rather be creative and look for the "good enough" approach to problem solving. I also understand that veteran programmers are already doing this on a much greater scale than this, and with greater intuition than I'm exhibiting. Perhaps this example could serve well for beginners, either way I would like to hear what y'all have to say.