More accurately, providing a fixed signature potentially removes the need for runtime dispatch of calling the varying functions. However, that doesn’t mean it’s as performant as compiling for specific functions. The lack of inlining has an inherent runtime cost for the call, and it also prevents various optimizations at compile-time.
Sort of. If the runtime dispatch dominates the runtime, then you’re seeing a large hit. If the various compiled functions take much longer, then the runtime dispatch is negligible. Julia compiles per call signature, so “function barriers” and type assertions (not necessarily fixed ones, can be generic and known at compile-time) can minimize the type-instability and runtime dispatches, and isolate them from the efficient compiled code.
Still, there are many cases where it’s worth removing runtime dispatch by communicating more information. FunctionWrappers.jl lets you specify a call signature and contain various functions’ compiled code. Despite describing some important limitations, the documentation is still scant so I’m linking my recent comment on it, the rest of the thread is worth reading too.