I am trying to get the most performant way to retrieve some properties associated to an ADT (I am using Moshi.jl, but I suspect the behavior with LightSumTypes et al. would be similar). Below I paste the code I am testing and the speeds I am benchmarking.
How is it possible to get mor performance out of ImmutableDict + manual dispatch than manual dispatch only?
Code definitions
import Base: ImmutableDict
using Moshi.Data: @data
using Moshi.Match: @match
abstract type AbstractADT end
@data MyADT <: AbstractADT begin
A
B
C
D
E
F
G
H
I
J
K
L
M
N
end
import .MyADT
const ADTType = MyADT.Type
struct ADTProperties
p1::Int64
p2::Float64
p3::String
p4::Char
end
const D_ADT::ImmutableDict{ADTType, ADTProperties} = ImmutableDict(
MyADT.A() => ADTProperties(1,1.0,"1",'1'),
MyADT.B() => ADTProperties(2,2.0,"2",'2'),
MyADT.C() => ADTProperties(3,3.0,"3",'3'),
MyADT.D() => ADTProperties(4,4.0,"4",'4'),
MyADT.E() => ADTProperties(5,5.0,"5",'5'),
MyADT.F() => ADTProperties(6,6.0,"6",'6'),
MyADT.G() => ADTProperties(7,7.0,"7",'7'),
MyADT.H() => ADTProperties(8,8.0,"8",'8'),
MyADT.I() => ADTProperties(9,9.0,"9",'9'),
MyADT.J() => ADTProperties(10,10.0,"10",'A'),
MyADT.K() => ADTProperties(11,11.0,"11",'B'),
MyADT.L() => ADTProperties(12,12.0,"12",'C'),
MyADT.M() => ADTProperties(13,13.0,"13",'D'),
MyADT.N() => ADTProperties(14,14.0,"14",'E'),
)
function get_property_manual(adt::ADTType)
x = @match adt begin
MyADT.A() => D_ADT[MyADT.A()]
MyADT.B() => D_ADT[MyADT.B()]
MyADT.C() => D_ADT[MyADT.C()]
MyADT.D() => D_ADT[MyADT.D()]
MyADT.E() => D_ADT[MyADT.E()]
MyADT.F() => D_ADT[MyADT.F()]
MyADT.G() => D_ADT[MyADT.G()]
MyADT.H() => D_ADT[MyADT.H()]
MyADT.I() => D_ADT[MyADT.I()]
MyADT.J() => D_ADT[MyADT.J()]
MyADT.K() => D_ADT[MyADT.K()]
MyADT.L() => D_ADT[MyADT.L()]
MyADT.M() => D_ADT[MyADT.M()]
MyADT.N() => D_ADT[MyADT.N()]
end::ADTProperties
return x.p1
end
function get_property_auto(adt::ADTType)
x = D_ADT[adt]
return x.p1
end
function get_property_full_manual(adt::ADTType)
return @match adt begin
MyADT.A() => ADTProperties(1,1.0,"1",'1')
MyADT.B() => ADTProperties(2,2.0,"2",'2')
MyADT.C() => ADTProperties(3,3.0,"3",'3')
MyADT.D() => ADTProperties(4,4.0,"4",'4')
MyADT.E() => ADTProperties(5,5.0,"5",'5')
MyADT.F() => ADTProperties(6,6.0,"6",'6')
MyADT.G() => ADTProperties(7,7.0,"7",'7')
MyADT.H() => ADTProperties(8,8.0,"8",'8')
MyADT.I() => ADTProperties(9,9.0,"9",'9')
MyADT.J() => ADTProperties(10,10.0,"10",'A')
MyADT.K() => ADTProperties(11,11.0,"11",'B')
MyADT.L() => ADTProperties(12,12.0,"12",'C')
MyADT.M() => ADTProperties(13,13.0,"13",'D')
MyADT.N() => ADTProperties(14,14.0,"14",'E')
end
end
Benchmarks
julia> @b rand(keys(D_ADT)) get_property_manual
2.057 ns
julia> @b rand(keys(D_ADT)) get_property_full_manual
2.280 ns
julia> @b rand(keys(D_ADT)) get_property_auto
2.285 ns