Typeof on Any vs Typeof on Union?

Hi everybody,

Is there a general explanation of why typeof comparisons on Any is 20 times slower than on Union in the following example ?
Especially, the huge memory allocation in one case but not in the other ?

Here is the output of the test:
First run ------------------------------

  • Typeof on union:
    1.301423 seconds
    Total=7898919599
  • Typeof on any:
    21.113947 seconds (657.92 M allocations: 16.339 GiB, 7.15% gc time, 0.05% compilation time)
    Total=7898919599

Second run ------------------------------

  • Typeof on union:
    1.055775 seconds (2 allocations: 32 bytes)
    Total=7898919599
  • Typeof on any:
    21.103012 seconds (657.92 M allocations: 16.339 GiB, 7.05% gc time)
    Total=7898919599

Here is the code:

struct Person
    name::String
    age::UInt8
end

struct Employee
    person::Person
    salary::Real
end

function sum_age(elements, repeat)
    total = 0
    for _ in 1:repeat, element in elements
        if typeof(element) === Person
            total += element.age
        elseif typeof(element) === Employee
            total += element.person.age
        end
    end
    return total
end

function test(size, repeat)
    person = Person("John", 41)
    employee = Employee(Person("Jane", 31), 1001.0)
    elements_any = Vector{Any}()
    elements_union = Vector{Union{Person,Employee}}()
    for _ in 1:size
        element = rand([person, employee])
        push!(elements_any, element)
        push!(elements_union, element)
    end

    println("First run ------------------------------")
    println("- Typeof on union:")
    @time total = sum_age(elements_union, repeat)
    println("  Total=", total)

    println("- Typeof on any:")
    @time total = sum_age(elements_any, repeat)
    println("  Total=", total)

    println()
    println("Second run ------------------------------")
    println("- Typeof on union:")
    @time total = sum_age(elements_union, repeat)
    println("  Total=", total)

    println("- Typeof on any:")
    @time total = sum_age(elements_any, repeat)
    println("  Total=", total)
end

test(123457, 1777)

FWIW, this may not answer your question exactly, but this pattern doesn’t have optimization support, as the expected way to write this is element isa Person

Useful advice @jameson
I will keep in mind to always prefer isa to typeof and === (am I right ?).
I checked that using isa in my example actually removes the issue and is faster.
Thanks

that is correct.