julia> using BenchmarkTools
julia> d=rand(10_000); m=rand(Bool, 10_000);
julia> @btime getindex($d,$m);
742.062 μs (23906 allocations: 643.13 KiB)
julia> Base.@propagate_inbounds function Base.iterate(L::Base.LogicalIndex, s)
# We're looking for the n-th true element, using iterator r at state i
n = s[1]
n > length(L) && return nothing
idx, i = iterate(Base.tail(s)...)
s = (n+1, s[2], i)
L.mask[idx] && return (idx, s)
while true
idx, i = iterate(Base.tail(s)...)
s = (n+1, s[2], i)
L.mask[idx] && return (idx, s)
end
end
julia> @btime getindex($d,$m);
49.477 μs (4 allocations: 38.63 KiB)
I first posted a completely wrong explanation, so I withdrew the bad post (my fault). Once I had the proper explanation, I made the work-around and submitted it as a PR.
The explanation I did not post here, btw, is that iterate(L::LogicalIndex{Int}) was not correctly inferred, because the state s can change type after the first iteration in the above loop. Unrolling the first iteration fixes that.