# Using Base.Iterators for optimization, good idea?

**URL:** https://discourse.julialang.org/t/using-base-iterators-for-optimization-good-idea/104717
**Category:** Performance
**Tags:** question
**Created:** [October 7, 2023, 10:15pm UTC](https://discourse.julialang.org/t/using-base-iterators-for-optimization-good-idea/104717 "2023-10-07T22:15:34Z")
**Posts on this page:** 1
**Page:** 1

<div class="post-metadata">

### Author: ![bguillen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bguillen/32/202173_2.png) [@bguillen](https://discourse.julialang.org/u/bguillen)
#### Post date: [October 7, 2023, 10:15pm UTC](https://discourse.julialang.org/t/using-base-iterators-for-optimization-good-idea/104717/1 "2023-10-07T22:15:34Z")

</div>

I implemented Hoare and Lomuto’s partitions with iterators. They behave as expected in terms of numbers of comparisons (`N-1`) and swaps (Hoare’s doing fewer than Lomuto’s).

However the benchmarks are giving me same times or even a bit better for Lomuto, even with the edge case of an all zeros vector (in which I have confirmed Hoare does `N/2` swaps and Lomuto does `N-1` swaps).

I wonder if the fact that I’m creating two iterators and zipping them (one of them reversed) in Hoare offsets the advantage of fewer swaps?

Here are the two functions:

```julia
function lomutopartitioniter!(arr::AbstractVector, pivot_index::Integer)
    @inbounds arr[pivot_index], arr[end] = arr[end], arr[pivot_index]
    pivot_value = arr[end]
    it_lr = Iterators.filter(p -> p[2] <= pivot_value, pairs(@view(arr[begin:end-1])))
    final_pivot_index = firstindex(arr)
    @inbounds for (j, _) in it_lr
        arr[final_pivot_index], arr[j] = arr[j], arr[final_pivot_index]
        final_pivot_index += 1
    end
    @inbounds arr[end], arr[final_pivot_index] = arr[final_pivot_index], arr[end]
    return final_pivot_index
end

```

```julia
function hoarepartitioniter!(arr::AbstractVector, pivot_index::Integer)
    @inbounds arr[pivot_index], arr[begin] = arr[begin], arr[pivot_index]
    pivot_value = arr[begin]
    # We take equal elements on both iterators to guarantee final pivot will be in the middle. 
    it_lr = Iterators.filter(p -> p[2] >= pivot_value, pairs(@view(arr[begin+1:end])))
    it_rl = Iterators.filter(p -> p[2] <= pivot_value, Iterators.reverse(pairs(@view(arr[begin+1:end]))))
    final_pivot_index = firstindex(arr)
    @inbounds for ((i1, _), (i2, _)) in Iterators.zip(it_lr, it_rl)
        final_pivot_index = firstindex(arr) + i2
        i1 >= i2 && break
        arr[begin+i1], arr[begin+i2] = arr[begin+i2], arr[begin+i1]
        final_pivot_index = firstindex(arr) + i1
    end
    if final_pivot_index == firstindex(arr)
        if isempty(it_lr)
            arr[begin], arr[end] = arr[end], arr[begin]
            return lastindex(arr)
        else
            return firstindex(arr)
        end
    end    
    @inbounds arr[begin], arr[final_pivot_index] = arr[final_pivot_index], arr[begin]
    return final_pivot_index
end

```

I tried using the profiler but honestly I’m not sure how to use it well.

Is there some optimization I can do here? Or is this a matter of how I am benchmarking?

Thank you!
