# Raytracing weekend: debugging unexpected allocations

Hello,

I’m new to Julia, and am out of ideas on how to prevent my code from allocating. I’ve made a fairly naive translation of the Raytracing Weekend program into Julia. I’m aware that I’m not the first person to do this, and when comparing my code to others’ it doesn’t seem that different, but it seems significantly slower. My code runs about 10x slower than the Rust implementation I wrote. I was hoping to get it much closer than that.

Here’s the function I’m trying to understand:

``````@inline function hit(sphere::Sphere, ray::Ray, tMin::Float64, tMax::Float64)::Union{HitRecord,Nothing}
oc = ray.origin .- sphere.center
a = lengthSquared(ray.direction)
half_b = dot(oc, ray.direction)
discriminant = (half_b * half_b) - (a * c)

if discriminant < 0
return nothing
end

sqrtd = sqrt(discriminant)
root = (-half_b - sqrtd) / a
if root < tMin || tMax < root
root = (-half_b + sqrtd) / a

if root < tMin || tMax < root
return nothing
end
end

t = root
p = at(ray, root)
outwardNormal = (p .- sphere.center) ./ sphere.radius
frontFace, normal = getFaceNormal(ray, outwardNormal)
HitRecord(p, normal, t, frontFace, sphere.material)
end
``````

Here’s a link to the full code on github if you want to see more context.

The very last line that creates a HitRecord is allocating. (Determined by running with `--track-allocation=user`.) I’ve tried a variety of things, including making Sphere generic over Material, and adding tons of extra type annotations, with no luck.

Most specifically, I’m trying to understand why there’s an allocation in this function where I’m returning an immutable struct. I’m guessing it still has something to do with how I’m storing `material`, but in this thread about optimizing the raytracing weekend code, the code’s structs are very similar, storing an abstract `Material` type on the `HitRecord`.

How do you represent 3D coordinates? as `Vector`?

In this case you can gain a lot by using `SVector` provided by the package `StaticArrays`. Statically sized means that the size can be determined from the type, which allows the compiler to make more aggressive optimizations.

Thanks! Yes, I’m using `StaticArrays`:

``````const Vec3 = SVector{3,Float64}
``````

I think that the issue is that in your `HitRecord` the `material` field is of abstract type `Material`, which will cause an allocation. In my own version (here) I use a union: `const Material = Union{Lambertian, Metal, Dielectric}`.