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 Ints, 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.