# Performance in broadcasting vs function preallocation?

**URL:** https://discourse.julialang.org/t/performance-in-broadcasting-vs-function-preallocation/126211
**Category:** Performance
**Tags:** question, performance, benchmarktools
**Created:** [February 23, 2025, 12:31pm UTC](https://discourse.julialang.org/t/performance-in-broadcasting-vs-function-preallocation/126211 "2025-02-23T12:31:05Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![lepton01](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lepton01/32/48824_2.png) [@lepton01](https://discourse.julialang.org/u/lepton01)
#### Post date: [February 23, 2025, 12:31pm UTC](https://discourse.julialang.org/t/performance-in-broadcasting-vs-function-preallocation/126211/1 "2025-02-23T12:31:05Z")

</div>

Hello there.  
I have created a couple of functions with the same purpose, evaluating:

```jl
f(x, y) = (x - 3)^2 + (y + 15)^2

```

over a matrix (really two vectors), the first column for `x` and the second one for `y`. The first function I made is this one:

```jl
function fitness(P::Array{Float64})
    v = Vector{Float64}(undef, size(P, 1))
    for ii in eachindex(v)
        v[ii] = f(P[ii, 1], P[ii, 2])
    end
    return v
end

```

after a while I realized the evaluation could be reduced to:

```jl
f.(a[:, 1], a[:, 2])

```

and both work perfectly.  
However, I do not completely understand the results of benchmarking, as the more complex function seems to take way less time. Why does this happen?  
Is it because preallocation? or the inherent allocations of broadcasting?

Code to benchmark:

```jl
using BenchmarkTools
a = rand(Float64, (1000, 2))
b = @benchmark fitness(a)
c = @benchmark f.(a[:, 1], a[:, 2])

```

with results:

 ![2025-02-23 13_28_02](https://global.discourse-cdn.com/julialang/original/3X/c/b/cbb59520571e8d9e25282162df83d2e432574ddd.png)

---

<div class="post-metadata">

### Author: ![yolhan\_mannes](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yolhan_mannes/32/220485_2.png) [@yolhan\_mannes](https://discourse.julialang.org/u/yolhan_mannes)
#### Post date: [February 23, 2025, 12:42pm UTC](https://discourse.julialang.org/t/performance-in-broadcasting-vs-function-preallocation/126211/2 "2025-02-23T12:42:32Z")

</div>

What happens if you simply put @views before the line f.() To avoid copying when slicing?

---

<div class="post-metadata">

### Author: ![abraemer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/abraemer/32/51403_2.png) [@abraemer](https://discourse.julialang.org/u/abraemer)
#### Post date: [February 23, 2025, 1:10pm UTC](https://discourse.julialang.org/t/performance-in-broadcasting-vs-function-preallocation/126211/3 "2025-02-23T13:10:26Z")

</div>

I think the main overhead you are seeing is from the _copies_ you perform when you write `a[:,1]`.  
Also you are benchmarking in global scope which might skew things a bit. Try:

```julia
using BenchmarkTools
a = rand(Float64, (1000, 2))
b = @benchmark $fitness($a)
c = @benchmark @views $f.($a[:, 1], $a[:, 2])

```

Apart from that: A broadcast is not very different from writing a straight-forward loop. In Julia loops are fast and you don’t to “vectorize” for performance like in Python.

---

<div class="post-metadata">

### Author: ![lepton01](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lepton01/32/48824_2.png) [@lepton01](https://discourse.julialang.org/u/lepton01)
#### Post date: [February 23, 2025, 1:35pm UTC](https://discourse.julialang.org/t/performance-in-broadcasting-vs-function-preallocation/126211/4 "2025-02-23T13:35:42Z")

</div>

Thank you, I forgot entirely of that aspect.

---

<div class="post-metadata">

### Author: ![lepton01](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lepton01/32/48824_2.png) [@lepton01](https://discourse.julialang.org/u/lepton01)
#### Post date: [February 23, 2025, 1:36pm UTC](https://discourse.julialang.org/t/performance-in-broadcasting-vs-function-preallocation/126211/5 "2025-02-23T13:36:54Z")

</div>

With this proposal, both seem to have the same performance now. May I ask, what does the `$` before the function call and variable means?

---

<div class="post-metadata">

### Author: ![abraemer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/abraemer/32/51403_2.png) [@abraemer](https://discourse.julialang.org/u/abraemer)
#### Post date: [February 23, 2025, 1:48pm UTC](https://discourse.julialang.org/t/performance-in-broadcasting-vs-function-preallocation/126211/6 "2025-02-23T13:48:33Z")

</div>

`$` generally means interpolation in Julia. You can e.g. interpolate strings:

> **[Strings · The Julia Language](https://docs.julialang.org/en/v1/manual/strings/#string-interpolation)**
>
> Documentation for The Julia Language.

But it is also commonly used in the context of macros when one want to insert expressions into other expressions. In this case it means that BenchmarkTools.jl inserts the value of the interpolated expression directly, i.e. it is not part of the benchmarking. Without interpolation in this case you include two things you don’t want: 1) lookup of the global variable `a` 2) a dynamic dispatch where Julia figures out which method it needs to call.

---

<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: [February 23, 2025, 2:00pm UTC](https://discourse.julialang.org/t/performance-in-broadcasting-vs-function-preallocation/126211/7 "2025-02-23T14:00:28Z")

</div>

> [@abraemer](#):
>
> `$f.`

`f` is a regular function, and therefore a const. It does not require interpolation. If `f` were a non-const variable holding an function, however, it should be interpolated.

If `f = sin`, interpolate, if `f(x) = sin(x)`, no need to interpolate.
