One area in which I’ve been concerned with the question of optimization vs. elegance is in the hp->midi word (a ‘word’ is Forth parlance for function / procedure / subroutine). This word takes the hp_ values (with a range of -hp_range/2 to hp_range/2), which io’s cognitive innards generate, and translates them into legal MIDI control values (0–127). hp->midi is called hundreds of times a second by io 0.0.1 beta (and perhaps will be called a greater number in io 0.0.1 beta++) so, if it hogs the system, the system may slow down unacceptably. (This was one of the words that I hand optimized when moving to floating point calculations of the hp_ coordinates.)
One of the changes I want to introduce in the move from io 0.0.1 beta to io 0.0.1 beta++ is a greater variability in its output character. A simple way to achieve this without changing the generative process at io’s core is to introduce different ways of deriving MIDI from the hp_ values. (I’ll write on this in more details in a future post.)
I’ve rewritten hp->midi to carry this out, and a quick (and very rough) benchmark suggests that, contrary to my initial fears, the new word is almost twice as fast as the old. Using the new version of hp->midi, the following code
0 hp->midi drop
took about 0.00127 milliseconds to execute, while using the new version, it takes about 0.00204 milliseconds.
Now you don’t get something for nothing and in this case the speed increase is offset by the time it takes for io++ to initialize (lots of slow floating point calculations), and greater memory usage. Basically, instead of doing these calculations on the fly as the old word did, io++ creates lookup tables during initialization. Thus hp->midi no longer calculates the MIDI values, but instead is a lookup routine, finding the corresponding value in an array with hp_range bytes.
More on this in the coming days…