Performance of Fields with Union Type

The Manual > Performance Tips documentation says that one should not use a field with an abstract type.

This makes sense to me as otherwise a lot of type lookup and method resolution would have to happen at runtime whenever you used that field.

On the other hand in the Manual > Types > TypeUnions says that Unions with a small number of types are still very efficient (Union is an abstract type however).

I have read Union-splitting: what it is, and why you should care which talks about Union Splitting. Will the compiler only do this optimization in the case of explicitly written Union types? Or will the compiler do so for a small type hierarchy as well?

For example one could write:

abstract type Side end
struct Bid <: Side end
struct Ask <: Side end

struct Trade
    ...
    s :: Side
end

Or alternatively write something very similar

struct Bid end
struct Ask end
const Side = Union{Bid, Ask}

struct Trade
    ...
    s :: Side
end

Would the performance of these be different? I.e would only the latter one use Union Splitting when you access the s field of a Trade or would both of them do so?

P.S

I understand that

struct Trade{T <: Side}
    ...
    s :: T
end

is the most efficient option, but I don’t believe that fits my use case as that would just cause type instability elsewhere in my code.

The performance will be different because in the first case, the compiler can’t prove that no one will ever add more subtypes to Side.

2 Likes

@Oscar_Smith What would happen if I hadn’t declared Side to be const? Would that also hinder performance then since someone could change Side?

And when you say the performance would be different, which one is better? The Union type one?

It doesn’t matter here if Side is a const. If Side isn’t const and gets updated after you create the struct, the struct definition won’t change. The Union will be faster.

2 Likes