# Why is this numerical scheme so much faster when using \`collect()\` than a for loop?

**URL:** <https://discourse.julialang.org/t/why-is-this-numerical-scheme-so-much-faster-when-using-collect-than-a-for-loop/77949>\
**Category:** Performance\
**Created:** [March 16, 2022, 5:57am UTC](https://discourse.julialang.org/t/why-is-this-numerical-scheme-so-much-faster-when-using-collect-than-a-for-loop/77949 "2022-03-16T05:57:30Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![maxkapur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maxkapur/32/21208_2.png) [@maxkapur](https://discourse.julialang.org/u/maxkapur)\
**Post date:** [March 16, 2022, 5:57am UTC](https://discourse.julialang.org/t/why-is-this-numerical-scheme-so-much-faster-when-using-collect-than-a-for-loop/77949/1 "2022-03-16T05:57:30Z")

</div>

Consider a toy algorithm that finds the maximum of a vector, then removes it and alters the other entries of the vector in a way that depends on whether they are located at a lower or higher index.

In the code below, why is the function `foo()` so much slower than `baz()`?

```julia
function foo(a::Vector)
    for j in 1:length(a)
        b, k = findmax(a)

        for i in 1:k-1
            a[i] = (a[i] + b) / 2
        end
        for i in k+1:length(a)
            a[i] = (a[i] + 1) / 2
        end

        deleteat!(a, k)
    end
end

function bar(a::Vector)
    for j in 1:length(a)
        b, k = findmax(a)

        deleteat!(a, k)

        a[:] = collect(
            i < k ? (a[i] + b) / 2 : (a[i] + 1) / 2
            for (i, c) in enumerate(a)
        )
    end
end

function baz(m::Int)
    a = rand(m)

    t_foo = @time foo(a) # 10.415122 seconds  
    t_bar = @time bar(a) # 0.000000 seconds
end

baz(100000)

```

I expected `foo()` to be faster, because it works individually on the indices as they come up, whereas `baz()` has to collect an entire new vector.

---

<div class="post-metadata">

**Author:** ![GunnarFarneback](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gunnarfarneback/32/1827_2.png) [@GunnarFarneback](https://discourse.julialang.org/u/GunnarFarneback)\
**Post date:** [March 16, 2022, 6:28am UTC](https://discourse.julialang.org/t/why-is-this-numerical-scheme-so-much-faster-when-using-collect-than-a-for-loop/77949/2 "2022-03-16T06:28:26Z")

</div>

If your measure claims that something that should take quite some time happens in basically no time, assume that your benchmarking is broken. In this case `foo(a)` mutates `a` and removes all elements. The call to `bar(a)` operates on an empty vector, which indeed is very fast.

---

<div class="post-metadata">

**Author:** ![maxkapur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maxkapur/32/21208_2.png) [@maxkapur](https://discourse.julialang.org/u/maxkapur)\
**Post date:** [March 16, 2022, 6:48am UTC](https://discourse.julialang.org/t/why-is-this-numerical-scheme-so-much-faster-when-using-collect-than-a-for-loop/77949/3 "2022-03-16T06:48:27Z")

</div>

Indeed you are right. Which makes it all the more mysterious why the for loop version is so much slower in my real application.

---

<div class="post-metadata">

**Author:** ![GunnarFarneback](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gunnarfarneback/32/1827_2.png) [@GunnarFarneback](https://discourse.julialang.org/u/GunnarFarneback)\
**Post date:** [March 16, 2022, 7:20am UTC](https://discourse.julialang.org/t/why-is-this-numerical-scheme-so-much-faster-when-using-collect-than-a-for-loop/77949/4 "2022-03-16T07:20:24Z")

</div>

When I’m faced with that kind of scenario I commit all my current changes, then start to aggressively cut down my code, while making sure the problem remains, until it’s small enough to explain itself or generate a Julia bug report. The latter outcome has become increasingly rare over time.

---

<div class="post-metadata">

**Author:** ![maxkapur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maxkapur/32/21208_2.png) [@maxkapur](https://discourse.julialang.org/u/maxkapur)\
**Post date:** [March 17, 2022, 2:34am UTC](https://discourse.julialang.org/t/why-is-this-numerical-scheme-so-much-faster-when-using-collect-than-a-for-loop/77949/5 "2022-03-17T02:34:38Z")

</div>

I was able to create an example that (I think) is benchmarked correctly. I created a new thread here: [Why is `collect()` faster than a for loop in this numerical scheme? (corrected!)](https://discourse.julialang.org/t/why-is-collect-faster-than-a-for-loop-in-this-numerical-scheme-corrected/78003)

I’d be very grateful if you could take a look.
