Hello! Fairly new to Julia, I’m having an unexpected performance issue in defining a function that returns a Iterators.filter
object.
I have a simulation that frequently requires me filtering all of my agents on some property, so I thought it would be DRY to capture that in a function – conditional_property_iterator
below. However, when I attempt to actually run that function, it’s making almost twice as many allocations as the raw iterator and taking almost 2x as long.
What am I missing here that’s causing this performance issue?
I’ve got an MRE below, any help would be greatly appreciated. Note the adding rand()
in the example below is just to do something inside the loop, rather than the actual logic I have in my simulation.
using BenchmarkTools
struct Thing
somevalue::Int
end
things = [Thing(rand(1:5)) for _ = 1:100000]
threes_getprop = Iterators.filter(a -> getproperty(a, :somevalue) === 3, things)
threes_prop = Iterators.filter(a -> a.somevalue === 3, things)
conditional_property_iterator(iterable, property::Symbol, value) = Iterators.filter(a -> getproperty(a, property) === value, iterable)
threes_cond = conditional_property_iterator(things, :somevalue, 3)
function test_threes_getproperty()
for i in threes_getprop
i.somevalue + rand(Int)
end
end
function test_threes_prop()
for i in threes_prop
i.somevalue + rand(Int)
end
end
function test_threes_cond()
for i in threes_cond
i.somevalue + rand(Int)
end
end
julia> @btime test_threes_getproperty()
2.834 ms (119301 allocations: 2.12 MiB)
julia> @btime test_threes_prop()
2.750 ms (119301 allocations: 2.12 MiB)
julia> @btime test_threes_cond()
4.491 ms (219301 allocations: 3.65 MiB)