As an example of the above:
julia> struct A
d::Vector{Int}
end
julia> struct B
d::Vector
end
julia> a = A([1,2,3])
A([1, 2, 3])
julia> b = B([1,2,3])
B([1, 2, 3])
julia> function f(x)
s = 0
for i in 1:length(x.d)
s += x.d[i]
end
s
end
f (generic function with 1 method)
julia> using BenchmarkTools
julia> @btime f($a)
2.473 ns (0 allocations: 0 bytes)
6
julia> @btime f($b)
94.774 ns (0 allocations: 0 bytes)
6
Note the huge difference in performance (there are no allocations here in either case, but in a different example there could be in when using B
). The difference is that in A
the vector can only be of Int
s, while the elements of b.d
could be of any type. Therefore, the compiler can build a specialized version of the function f
knowing that a.d
will be a vector of integers, and that is fast, but it cannot know in advance that the vector d
of structure of type B
is of integers or anything else, so it cannot specialize its operations.
The same happens in your case, but with the size of the arrays. So you either build your structure with a fixed type and size of array (Vector{T}
or Matrix{T}
, or Array{T,2}
, etc), or just let the entire type of the array be on the signature of the type, such as:
julia> struct A{T}
m::T
end
julia> a = A([1,2,3])
A{Vector{Int64}}([1, 2, 3])
Now a function will be specialized for exactly A{Vector{Int64}}
, and if you start an instance of A
with a different type of array, like:
julia> a = A([1 2
3 4])
A{Matrix{Int64}}([1 2; 3 4])
functions that work on these will be specialized to A{Matrix{Int64}}
instead.