I was trying out a few different ways a model I am working one. The baseline is just 3xN array of floats to represent x,y,z coordinates of N points. Next I tried to create a Point-type to describe the point and use a Vector of Points to represent the N points. I have a case where I need to select some points based on the Z-coordinate. In my example the vector of Points is significantly slower than using a 3xN array. Also a lot more allocations. I was expecting some overhead on the Point-type solution but nothing like I am seeing. What am I missing?

using BenchmarkTools
struct Point
x
y
z
end
function selectionBelow(p::Point, val)
p.z < val
end
function selectionBelow(A, val)
B = view(A,3,:)
B .< val
end
# Generate data
A = rand(3, 200000)
points = Vector{Point}(undef,size(A,2))
for idx in axes(A,2)
points[idx] = Point(A[1,idx], A[2,idx], A[3,idx])
end
# Evaluate
tol = 0.3
sel1 = @btime selectionBelow(A, tol);
sel2 = @btime selectionBelow.(points, tol);

Your struct members have type Any, which means they cannot be stored inline, and that efficient specialized code cannot be generated, since the fields can be of any type whatsoever. You must give the fields a concrete type, or a parametric type.

Thank you for the suggestion. I am not sure if it makes sense for my benchmark, in any real application I would need to pass data to the function. I usually see the $ (dollar sign) in cases where the benchmark call includes a call to rand(). Then to avoid the benchmarking to include rand() they use the dollar sign. Am I missing something?

o, it isn’t just for rand
With the $ you say to treat the variable as a local variable (as will be in the actual implementation), even if you are benchmarking on the global scope…