I the performance section, it was stated that we should avoid fields with abstract types
struct MyAmbiguousStruct
val::AbstractFloat
end
But what about incompletely parameterized types? How bad is something like
struct MyGenericArrayStruct{T}
val::Array{T}
end
when compared to
struct MyGenericVectorStruct{T}
val::Array{T,1}
end
I’m asking because it is useful for me to have structs that could have array multiple fields with different dimensions, but it becomes unwieldy to have ALL the dimension parameters show up in the parent struct. Is the performance penalty for an “incompletely parameterized type” the same as an abstract type?
In general, “it depends” - you could incur a lot of overhead (particularly in a hot loop), and you’d be making life harder for the compiler, but the flexibility may be worth it if runtime isn’t critical. The only way to answer the question of performance penalty for your particular application is through benchmarks, but just to give you a rough idea, compare:
julia> abstract type GenericContainer end
julia> struct MyGenericArrayStruct{T} <: GenericContainer
val::Array{T}
end
julia> struct MyGenericVectorStruct{T} <: GenericContainer
val::Array{T,1}
end
julia> total(g::GenericContainer) = sum(g.val)
total (generic function with 1 method)
julia> using BenchmarkTools
julia> mgas = [MyGenericArrayStruct(rand(3)) for i = 1:10^6];
julia> mgvs = [MyGenericVectorStruct(rand(3)) for i = 1:10^6];
julia> @btime mapreduce(total, +, $mgas)
63.524 ms (1999999 allocations: 30.52 MiB)
1.5007591209103481e6
julia> @btime mapreduce(total, +, $mgvs)
6.469 ms (0 allocations: 0 bytes)
1.499610642683319e6
directly, if you find cumbersome to annotate T,N in your case. You could create an inner constructor to check the data structure if that is needed for some reason.