It should help if you make the compiler compile functions for every fieldname, and it wont for Symbol. But you can force multiple versions using Val{:x}(). Have a wrapper function that will constant propagate the symbol (i.e. @inline), then wrap it with Val and call the method again.
Oh I see you tried that - but it does work, I use it everywhere for this kind of thing:
struct Hit
dom_id::Int16
time::Float64
end
@inline function categorize_val(field::Symbol, elements::Vector)
categorize_val(Val{field}(), elements)
end
@inline function categorize_val(field::Val{F}, elements::Vector{T}) where {T,F}
out = Dict{fieldtype(T, F), Vector{T}}()
for el ∈ elements
key = getfield(el, F)
if !haskey(out, key)
out[key] = T[]
end
push!(out[key], el)
end
out
end
n = 20
dom_ids = Int16.(rand(1:4, n))
times = rand(n);
hits = [Hit(dt...) for dt in zip(dom_ids, times)]
using BenchmarkTools
julia> @btime categorize_val(:dom_id, $hits)
853.000 ns (14 allocations: 1.41 KiB)
Dict{Int16,Array{Hit,1}} with 4 entries:
4 => Hit[Hit(4, 0.642627), Hit(4, 0.491384), Hit(4, 0.981954)…
2 => Hit[Hit(2, 0.211748), Hit(2, 0.000746403), Hit(2, 0.7723…
3 => Hit[Hit(3, 0.511963), Hit(3, 0.386519), Hit(3, 0.207365)…
1 => Hit[Hit(1, 0.908978), Hit(1, 0.768637), Hit(1, 0.449042)…