I poked around a bit but did not find guidelines on when a simple opportunity for optimization should be taken. I’m not concerned about end-user code, rather both the core and packages. Perhaps the main issue is code complexity / compilation time vs. efficiency. Does something like this exist ? Or maybe there is an unwritten consensus. It’s a practical question for people who make a PR, but don’t follow the Julia issues and PRs closely. An example: This is the current code for
merge! (there are a couple of other methods that are irrelevant here).
function merge!(d::AbstractDict, others::AbstractDict...) for other in others for (k,v) in other d[k] = v end end return d end
Say for the sake of argument that the following is faster for any collection of
AbstractDicts. (In fact it is faster for several cases with not only two, but also three
function merge1!(d::AbstractDict, others::AbstractDict...) for other in others merge1!(d,other) end return d end function merge1!(d::AbstractDict, other::AbstractDict) for (k,v) in other d[k] = v end return d end
I don’t want to focus too much on
merge! here, its just an example. But, I am only interested in cases, like this one, where there is no observable difference. Here are a few choices
- Choose the shorter code if the difference in speed is at most 50%. (Or number of allocations, etc.)
- If the efficiency factor is constant (not “algorithmic”) and not causing complaints, choose the less complex code until v1.0 is released. The reason is that the implementation and even user-facing API may change. After v1.0, choose the more efficient implementation.
- Wait till v1.0, but ask more subtle questions. How often and where is the code called?. E.g. you can accept a lot of complexity to make
sinefficient. Or you may want to wait until the user base grows in order to better inform larger-scale design choices. In other words, be conservative with premature optimization.
- For examples like the one above, choose the simpler code and wait for a compiler optimization. But, even if the optimization is implemented, how can you be sure it’s applied to your code? I am thinking of the argument for one of the advantages of syntactic loop fusion; you know that the optimization is made. I recall using the C preprocessor because the compiler’s heuristic for inlining was not good enough, and I didn’t want to waste time monitoring and tinkering with flags. In the case above, one could prototype the optimization with macros. Because we have syntactic macros, this can be done safely and you don’t even need to be a compiler-person.
It may be difficult to write a somewhat simple set of guidelines on this.