Six Billion Unnecessary Function Calls
And no, the program still doesn't really need optimization
Features should be prioritized over performance until you physically run out of resources.
The Offending Program
LM is a compiler and/or typed macro assembler. It is self-hosting, so any features that it relies on need to be supported by compiling itself. Compilation currently takes about 40 seconds to complete, which is quite slow considering how barebones the codebase is. So, to start addressing this issue I decided to profile a bit.
The results of profiling indicated that some important functions were being called over 3 billion times each! I knew the codebase was in a somewhat unfortunate state, so this really didn’t surprise me at all. However, what did surprise me was how fast this runs on a single core. A quick google search indicates that a modern processor can handle “200 billion operations per second” which seems about right empirically.
When To Optimize
I previously had made a conscious decision to avoid optimization and try to work on feature development for as long as possible. This turned out to be a good decision as LM is now more capable of addressing these performance problems with good well-engineered solutions.
In general I would recommend avoiding optimization for as long as possible. Only blocking performance issues should merit hand-optimization. There is also a bit to be said about the role of good compilers for optimization. Some optimizing compilers can reduce the impact of poor quality code by performing intelligent optimizations.
Low-level Optimization
LM as an assembler is the final step in compilation. If the optimizations don’t get added before creating object files, then they never will be applied. Low-level optimizations are a good fit for LM because it is pure profit.
Most programmers by comparison probably wouldn’t benefit too much from optimizing low-level representations. O3
optimizations can be surprisingly efficient and intelligent. Just turn them on and watch the performance improve.
High-level Optimization
Algorithmic optimizations are good for everybody. Rearchitecting code can accomplish similar objectives with far fewer resources. Rearchitecting code also comes with the benefit that your code will be easier to read and maintain.
High-Level Optimization is good for everybody and is a healthy investment into the project.
Conclusion
“Premature optimization is the root of all evil.”