I’m trying to understand if there’s optimization potential in Makie regarding its ubiquitous use of keyword arguments. My idea is writing a macro that makes a function gather its keyword arguments not into a NamedTuple
but into a Dict{Symbol,Any}
. That type would, when passed down to callees, only cause one compilation, while a NamedTuple
needs a new one for each combination of keywords and types.
The simplest thing I can do is of course just to gather all keyword arguments into a dict manually wherever needed:
function myfunction(; kwargs...)
d = Dict{Symbol,Any}(kwargs)
do_something_else(d)
end
But this still incurs a NamedTuple
specialization at the level of Core.kwcall
for every call, I think.
Has anyone ever measured if all these named tuples are a problem for the compiler? For example every one of these calls compiles a new one:
scatter(...; color = :red)
scatter(...; color = "red")
scatter(...; color = "red", marker = :rect)
scatter(...; color = "red", marker = :rect, markersize = 1)
But it seems this behavior is baked deep into the language because it happens directly at the lowering stage, both when defining a function with keyword arguments and when calling it. I understand it’s better for final performance, but for “bag of keyword argument” interfaces like Makie has it’s not great.
If I wanted to overload the kwcall
behavior, can I overload the helper function that gets created at function definition? It’s name is gensymmed and I’m not sure how it’s supposed to be retrieved after the fact (var"#myfunction#131"
in this case):
julia> Core.kwcall(Dict(:a => 1), myfunction)
ERROR: MethodError: no method matching var"#myfunction#131"(::Dict{Symbol, Int64}, ::typeof(my_function))
Closest candidates are:
var"#myfunction#131"(::Base.Pairs{Symbol, V, Tuple{Vararg{Symbol, N}}, NamedTuple{names, T}} where {V, N, names, T<:Tuple{Vararg{Any, N}}}, ::typeof(my_function))
In Makie, there are many methods that take both a positional ::Attributes
argument (that’s just a special Dict) and ; kwargs...
, so it would be cool to be able to overwrite the kwcall
behavior for a whole number of functions to just immediately merge their kwargs
into the positional Attributes
arg automatically (without manually doing this step everywhere, but maybe that is the easiest path after all).