I have a type-stability question. In my 2D axisymmetric ray tracing code, I define an array of surfaces that has the type Union{Cone, Plane}, like
surfaces = Matrix{Union{Cone, Plane}}(undef, 100, 2)
All of them should in principle be cones, but due to small errors from a discretization earlier on in the code, there might be a few adjacent points that end up defining a plane, thus the Union. Which elements are Plane exactly is not known until the geometry is created.
For context, the type hierarchy goes like:
abstract type Reflection end
abstract type Surface end
struct ReflectionDiffuse <: Reflection end
struct ReflectionSpecular <: Reflection end
struct Cone{T<:Reflection} <: Surface
reflection::T
end
struct Plane{T<:Reflection} <: Surface
reflection::T
end
In the part of the code that checks the intersection, I’m looping over all surfaces (looping over i and j) and checking for intersections. The function call is something like
check_intersection!(surfaces[i, j], otherargs...)
It’s important to dispatch on the correct check_intersection! function based on the type of the surface as it then determines the calculation of other things like the normal and tangent vectors later on.
The problem is that a @code_warntype analysis reveals red-colored text in this function call in Union{Cone, Plane}, and it’s causing a 10x slowdown in performance and a huge number of allocations (millions to billions). I think I know why it’s type-unstable - the code is boxing all elements of surfaces - but I’m not sure how to make this type-stable.
This related question on StackOverflow suggests to create a Union and claims that since the Union is small, performance should still be good…