I have also spent an endless number of hours in SnooptCompile to achieve improvements of 1-2 seconds in compile time. One thing that I really can’t understand is why taking the size or length of a var that is Any returns an Any.
Damn it, size can only be an Int.
julia> struct Bad <: AbstractVector{Int} end
julia> Base.size(::Bad, args...) = missing
Where is your god now?
Joking aside, the problem is that the compiler can’t prove that someone didn’t do the equivalent of what I just did above. That’s why it needs to return Any.
I wont go into discussing this as it quickly dives into territories where I cannot go, but it seems a week reason. If it can’t just error. The docs seem clear
size(A::AbstractArray, [dim])
Return a tuple containing the dimensions of A.
Knowing it’s gotta be an Integer is, really, not any better than Any for the purposes of the compiler and possible runtime speed. It still needs the costly indirection to figure out what instructions to use, and it can’t just shove it into a 64-bit register.
It’s not literally returning Any — the compiler just isn’t sure what it might return at runtime. And it’s because the compiler doesn’t know what type val will be, so it doesn’t know what method of string will be called.
Just as in the size example, the trouble isn’t so much string (or size), but upstream of that — sort out the stability of their arguments and they’ll then be stable.
Maybe not, but what I know is the module in question is precompiled and it still takes a further ~6 seconds to run on the first run. I try to reduce that and the only thing I can tie to the the potential instabilities … and ~zero success.
As @mbauman says it’s something else in the function thats unstable. You can fix that, or if thats not possible split the function into 2 functions to create a function barrier, so as much of it as possible is stable.
I know that, but in this case it’s an impossible task because those are derived from input arguments to the function and they can have different types. Nothing really important for run time … as long as per-compilation had worked well. But it didn’t and I’m just trying to find out why and the Any's are the beasts to chase, so we are told.
And to give it more context, this the function I’m referring to https://github.com/GenericMappingTools/GMT.jl/blob/master/src/psxy.jl#L7. The source of the Any's is the kwargs tht are converted into a Dict(:symbol, Any) and from there anything extracted from the Dict is a Any. Have no idea on how to work around this.
But again, this does not seem to hurt runtime … after compilation of first run, hence latency.
Type instabilities in end-packages tend to impact runtime speed, not the (pre-)compile time. In upstream libraries, yes, they can indeed become one of the magnets for invalidation, but I don’t think they’re typically troublesome at the point where I think you are.