Inspired by Zero-Cost Abstractions I tried to implement field based access for a dictionary. It kinda works, but could it be improved? Why isn’t the last function working as fast as it should? I’m using julia v1.0.3.
j and f benchmark the same for me; in fact their code_llvm is the same. Looks like the type-unstable Val creation is being constant-folded.
Lifting values into the type system can only serve to slow things down in this case (or give the same performance if the compiler optimizes it away, as with j). No amount of type system trickery can make the Dict lookup faster.
BTW, you need to use Base.@_inline_meta as the first statement in the expression returned by @generated functions instead of @inline @generated. E.g. as in
Why do you need @generated at all here? You’re still doing the dictionary lookup in the generated code. The thing about the blog post you linked is that it does the lookup outside the generated expression, at compile time (hence “zero-cost”). Is that what you wanted to do here as well, or did you just want to implement field based dictionary access?
I mainly wanted to achieve what @tkoolen has figured it out with ImmutableDict - so there and no dictionary lookups at all, you are right, @generated is not needed there.
But I also wanted to have other fields in A still accessible and have correct type information. Not sure if it is possible without @generated and Val trick.
A simple if tree will do in this case. If the property name is a constant, the optimizer will optimize away everything but the relevant branch, making the function type stable.
struct A{T}
__dict::Dict{Symbol, T}
end
function Base.getproperty(a::A, s::Symbol)
if s === :__dict
return Core.getproperty(a, :__dict)
else
return Core.getproperty(a, :__dict)[s]
end
end
f(a) = a.x
g(a) = a.__dict