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…