# Too much garbage collection for a simple vector addition operation

**URL:** https://discourse.julialang.org/t/too-much-garbage-collection-for-a-simple-vector-addition-operation/102173
**Category:** Performance
**Tags:** question, array, vector, garbage-collection
**Created:** [July 27, 2023, 7:48pm UTC](https://discourse.julialang.org/t/too-much-garbage-collection-for-a-simple-vector-addition-operation/102173 "2023-07-27T19:48:51Z")
**Posts on this page:** 13
**Page:** 1

<div class="post-metadata">

### Author: ![ducanh-le](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ducanh-le/32/51862_2.png) [@ducanh-le](https://discourse.julialang.org/u/ducanh-le)
#### Post date: [July 27, 2023, 7:48pm UTC](https://discourse.julialang.org/t/too-much-garbage-collection-for-a-simple-vector-addition-operation/102173/1 "2023-07-27T19:48:51Z")

</div>

Hi everyone,

I’m trying to optimize my code. When look at the profiler, the 2nd and the 3rd line below got GC flags:

```plaintext
function resourceAvailable(v::Int32, a::Int32, usedResource::Vector{Int32}, md::ModelData)
    neededResource::Vector{Int32} = usedResource .+ md.r[md.ct[v]][a]
    return all(x -> x >= 0, md.cap .- neededResource), neededResource
end

```

This is my **ModelData** struct:

```plaintext
struct ModelData
        ct::Vector{Int32}
        cap::Vector{Int32}
        r::Vector{Vector{Vector{Int32}}}
end

```

I tried some things in the **StaticArrays** package but nothing help. Can someone please explain why? Here is the profiler result:

![image](https://global.discourse-cdn.com/julialang/original/3X/8/5/85a8dc08161444f6217607f36b762c4a80ddcfcf.png)

Thanks.

---

<div class="post-metadata">

### Author: ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)
#### Post date: [July 27, 2023, 7:54pm UTC](https://discourse.julialang.org/t/too-much-garbage-collection-for-a-simple-vector-addition-operation/102173/2 "2023-07-27T19:54:30Z")

</div>

> [@ducanh-le](#):
>
> `md.r[md.ct[v]][a]`

if `md.ct[v]` is a vector, maybe use `@views` in front of this line could help

---

<div class="post-metadata">

### Author: ![ducanh-le](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ducanh-le/32/51862_2.png) [@ducanh-le](https://discourse.julialang.org/u/ducanh-le)
#### Post date: [July 27, 2023, 7:59pm UTC](https://discourse.julialang.org/t/too-much-garbage-collection-for-a-simple-vector-addition-operation/102173/3 "2023-07-27T19:59:04Z")

</div>

Hi,

If you mean:

```plaintext
@views neededResource::Vector{Int32} = usedResource .+ md.r[md.ct[v]][a]

```

I tried it, nothing change ☹

---

<div class="post-metadata">

### Author: ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)
#### Post date: [July 27, 2023, 8:11pm UTC](https://discourse.julialang.org/t/too-much-garbage-collection-for-a-simple-vector-addition-operation/102173/4 "2023-07-27T20:11:20Z")

</div>

something must changed, because before you’re allocating `md.r[md.ct[v]]` now you’re not.

But otherwise yeah, if this is what you need to do, nothing can be optimized

---

<div class="post-metadata">

### Author: ![ducanh-le](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ducanh-le/32/51862_2.png) [@ducanh-le](https://discourse.julialang.org/u/ducanh-le)
#### Post date: [July 27, 2023, 8:23pm UTC](https://discourse.julialang.org/t/too-much-garbage-collection-for-a-simple-vector-addition-operation/102173/5 "2023-07-27T20:23:35Z")

</div>

Sorry I don’t understand. It’s not just accessing? Why does it need to allocate something?  
And **md.ct[v]** is an integer, not a vector.

---

<div class="post-metadata">

### Author: ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)
#### Post date: [July 27, 2023, 8:50pm UTC](https://discourse.julialang.org/t/too-much-garbage-collection-for-a-simple-vector-addition-operation/102173/6 "2023-07-27T20:50:34Z")

</div>

> [@ducanh-le](#):
>
> ```julia
> neededResource::Vector{Int32} = usedResource .+ md.r[md.ct[v]][a]
> return all(x -> x >= 0, md.cap .- neededResource), neededResource
> 
> ```

Both `.` (dot) operations allocate new arrays. The second one can be completely avoided, using,  
for example\*:

```julia
all(>=(0), md.cap[i] - neededResource[i] for i in eachindex(md.cap, neededResource))

```

(using both arrays in `eachindex` will guarantee that the operation is inbounds, but you could in put only one of them for simplicity)

The first one is allocating a new array `neededResource`, and the only way to avoid that is to preallocate it outside the function, to make the function in-place.

\* there are alternatives, for example:

```julia
all(>=(0), x[1] - x[2] for x in zip(md.cap, neededResource))

```

---

<div class="post-metadata">

### Author: ![ducanh-le](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ducanh-le/32/51862_2.png) [@ducanh-le](https://discourse.julialang.org/u/ducanh-le)
#### Post date: [July 27, 2023, 11:04pm UTC](https://discourse.julialang.org/t/too-much-garbage-collection-for-a-simple-vector-addition-operation/102173/7 "2023-07-27T23:04:05Z")

</div>

Thank you!  
I modified the function according to your suggest:

```plaintext
function resourceAvailable(usedResource::Vector{Int32}, neededResource::Vector{Int32}, actResource::Vector{Int32}, capResource::Vector{Int32})
    @inbounds for i in eachindex(neededResource, usedResource, actResource)
        neededResource[i] = usedResource[i] + actResource[i]
    end
    return all(>=(0), capResource[i] - neededResource[i] for i in eachindex(capResource, neededResource))
end

```

And All the GC flags gone!

---

<div class="post-metadata">

### Author: ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)
#### Post date: [July 28, 2023, 12:10am UTC](https://discourse.julialang.org/t/too-much-garbage-collection-for-a-simple-vector-addition-operation/102173/8 "2023-07-28T00:10:10Z")

</div>

> [@ducanh-le](#):
>
> ```julia
> @inbounds for i in eachindex(neededResource, usedResource, actResource)
> neededResource[i] = usedResource[i] + actResource[i]
> end
> 
> ```

This loop is totally fine. But you can write it as:

```julia
neededResource .= usedResource .+ actResource

```

or

```julia
@. neededResource = usedResource + actResource

```

The broadcasts won’t allocate now that you are updating an existing array.

---

<div class="post-metadata">

### Author: ![sijo](https://avatars.discourse-cdn.com/v4/letter/s/da6949/32.png) [@sijo](https://discourse.julialang.org/u/sijo)
#### Post date: [July 28, 2023, 10:29am UTC](https://discourse.julialang.org/t/too-much-garbage-collection-for-a-simple-vector-addition-operation/102173/9 "2023-07-28T10:29:20Z")

</div>

Another alternative for the second broadcasting line:

```julia
all(>=(0), Iterators.map(-, md.cap, neededResource))

```

---

<div class="post-metadata">

### Author: ![mikmoore](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikmoore/32/31109_2.png) [@mikmoore](https://discourse.julialang.org/u/mikmoore)
#### Post date: [July 28, 2023, 2:17pm UTC](https://discourse.julialang.org/t/too-much-garbage-collection-for-a-simple-vector-addition-operation/102173/10 "2023-07-28T14:17:34Z")

</div>

Why not combine the predicate and subtraction? The optimizer can probably resolve this, but it seems like messy code to write. But really, why subtract and compare to 0 when you can compare the numbers directly?

```julia
all(splat(>=), zip(md.cap, neededResource))

```

---

<div class="post-metadata">

### Author: ![ducanh-le](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ducanh-le/32/51862_2.png) [@ducanh-le](https://discourse.julialang.org/u/ducanh-le)
#### Post date: [July 28, 2023, 4:27pm UTC](https://discourse.julialang.org/t/too-much-garbage-collection-for-a-simple-vector-addition-operation/102173/11 "2023-07-28T16:27:36Z")

</div>

Hmm you are right that sound logic I’ll do that! Thanks.

---

<div class="post-metadata">

### Author: ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)
#### Post date: [July 28, 2023, 4:56pm UTC](https://discourse.julialang.org/t/too-much-garbage-collection-for-a-simple-vector-addition-operation/102173/12 "2023-07-28T16:56:08Z")

</div>

> [@mikmoore](#):
>
> `all(splat(>=), zip(md.cap, neededResource))`

Or, arguably a bit more readable:

```julia
all(md.cap[i] >= neededResource[i] for i in eachindex(md.cap))

```

---

<div class="post-metadata">

### Author: ![sijo](https://avatars.discourse-cdn.com/v4/letter/s/da6949/32.png) [@sijo](https://discourse.julialang.org/u/sijo)
#### Post date: [July 29, 2023, 7:16am UTC](https://discourse.julialang.org/t/too-much-garbage-collection-for-a-simple-vector-addition-operation/102173/13 "2023-07-29T07:16:02Z")

</div>

Or

```julia
all(Iterators.map(>=, md.cap, neededResource))

```
