I count roughly 11 Discourse threads in the past 6 months linking to the near-infamous performance tip regarding when Julia avoids specializing to resolve performance issues. The purpose of this thread is to re-visit this choice of default behavior and consider whether an alternative may be preferable.
To re-cap: there are three cases where Julia may choose to not specialize on an argument type: Function
, Type
, and Vararg
. This non-specialization can save the compiler the effort of recompiling functions for different argument types that actually have little/no effect on the generated code. It is possible to override this default by adding otherwise-unnecessary parametric annotations to those arguments in the method signature. It is possible to force non-specialization on other types with the use of @nospecialize
or other code patterns. Using an otherwise non-specialized argument explicitly within the function body will usually cause specialization (although I recall seeing cases where it doesnât), but not always and the prevailing advice of âwrite short functions for clarity and rely on inlining to remove the costâ works against this.
The current default seems to lead directly to ~2 issues per month on Discourse, although the iceberg probably goes much deeper in its (un-noticed or ignored) effect on members of the community. My speculation is that, âon average,â user code would see performance benefits (even accounting for regression due to extra compilation) if we removed some or all of the three special cases (and re-add the current behavior in a few key snippets that rely on the current default).
For my use code, personally, Iâve overridden almost every place where Iâve noticed this non-specialization in effect because I only ever use the functions in question with a small number of argument types within a session (so the compiler/memory load is modest) and the non-specialization results in considerable performance losses.
The non-specialization is definitely important, but the places it is important are often places like Base
or package code where it might be used diversely within a single application. This code is contributed by (or at least reviewed by) veteran users who can be expected to know the performance tips and who are putting extra effort into this re-usable code. With a change to the default, it would become necessary to annotate some sites as @nospecialize
for the same reason the current defaults exist, but I suspect that code outside of Base
and a small set of packages would require many fewer annotations than we use now.
Going out on a limb, I suspect that âaverageâ performance across existing Julia code (most of which is private and written by individuals with shallower knowledge than Discourse regulars) would be positively affected by a changed default. And I think that âthis code seems slow to compileâ is a more suitable and less frequent issue to require Discourse help (if a bit more complicated to diagnose and resolve) than the âthis code is slow and allocates a ton even though Iâve done everything right except to know this special exceptionâ issues we see currently.
If itâs worth changing the default in only a subset of these three cases, thatâs also worth considering.