Performance of structs with incompletely parameterized fields


I the performance section, it was stated that we should avoid fields with abstract types

struct MyAmbiguousStruct

But what about incompletely parameterized types? How bad is something like

struct MyGenericArrayStruct{T}

when compared to

struct MyGenericVectorStruct{T}

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

julia> struct MyGenericVectorStruct{T} <: GenericContainer

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)

julia> @btime mapreduce(total, +, $mgvs)
  6.469 ms (0 allocations: 0 bytes)
1 Like

You could add also the dimension as a type parameter to the wrapping type, that way you’d have both performance a d flexibility.

And you can also use

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.