I am setting up a multiple dispatch structure and get unexpected allocations when I use more than 3 dispatch types as illustrated in the MWE below:
Consider the following composite types:
for T in (:A, :B, :C)
@eval begin
struct $T
n::Int
end
end
end
Now let’s make a general wrapper type:
struct General
d::DataType
n::Int
end
With this let’s define a method for creating A
through C
(3 types using dispatch):
f3(g::General) = f3(g.d, g)
for T in (:A, :B, :C)
@eval begin
f3(::Type{$T}, g) = $T(g.n)
end
end
Before we test this, let’s add one more composite type D
and setup a method f4
that dispatched off of 4 types:
struct D
n::Int
end
f4(g::General) = f4(g.d, g)
for T in (:A, :B, :C, :D)
@eval begin
f4(::Type{$T}, g) = $T(g.n)
end
end
Ok, now let’s setup let’s compare:
gs = [General(A, i) for i in 1:1000]
function test(f, gs)
for g in gs
f(g)
end
end
test(f3, gs)
test(f4, gs)
@time test(f3, gs)
@time test(f4, gs)
0.000009 seconds
0.000101 seconds (2.00 k allocations: 46.875 KiB)
Hence, the dispatch only using 3 types does not allocate as expected, but once 4 or more types are used it allocates and is an order of magnitude slower.
Could someone kindly provide an explanation and/or a workaround? Thanks!