Currently, the approach to enabling direct linking (DL) is mostly all-of-nothing with pinpoint opt-out (^:redef
). In my experience, it makes using DL somewhat awkward in production cases where you still want to retain the ability to jack into the application for debugging and investigation purposes. Knowing upfront which functions you would need to recompile is cumbersome and mentally taxing. In fact, I end up not enabling DL at all because of it.
I wonder if having a more flexible way to tune DL would make it more popular. Here are my thoughts pertaining to this.
Currently, the decision whether to DL is made at the callsite depending on the value of *compiler-options*
at the moment of compiling that callsite. The alternative I envision is when the decision to DL is made at the function definition time, and all the future invocations of that function honor that decision.
Let me give you an example. Clojure itself compiles clojure.core
namespace with DL enabled. This means that functions within clojure.core
statically link to other clojure.core
functions. However, if the developer has DL disabled, then the calls to clojure.core
functions would go through Var resolution. I personally can't envision a scenario where this precise behavior is desired. Would someone want to redefine a clojure.core
function for the code they run while being content with an old version still being used by some other code? Is this something that the language design wants to encourage?
My second point is that a blanket DL usually brings quite unsubstantial performance improvements except when used for specific functions called in tight loops that are amenable to JIT cascade optimizations due to inlining. Such performance-critical functions can be reliably identified by the developer with a help of a profiler, and then it makes sense to only enable DL for those functions. As of now, the only way to make a function that is guaranteed to be JIT-inlinable without going buying into DL wholesale is to use the semi-obscure :inline
function which is just a macro, after all.
On the implementation side, this could be implemented by a combination of a special value of *compiler-options* :direct-linking
(kinda similar to how *unchecked-math*
can just be true
or :warn-on-boxed
) and a metadata on Vars (could reuse the currently noop ^:static
).
TL;DR: I'd like a mode of DL when all callsites of a function compiled with DL to be directly linked automatically, and a way to explicitly mark a function to always use DL. Does anybody else find something like this useful? Would love to hear what you think.