# Julia function performance behaving strange when combining broadcasting, a NamedTuple of Parameters, and a function as argument

**URL:** https://discourse.julialang.org/t/julia-function-performance-behaving-strange-when-combining-broadcasting-a-namedtuple-of-parameters-and-a-function-as-argument/23888
**Category:** Performance
**Created:** [May 5, 2019, 11:22pm UTC](https://discourse.julialang.org/t/julia-function-performance-behaving-strange-when-combining-broadcasting-a-namedtuple-of-parameters-and-a-function-as-argument/23888 "2019-05-05T23:22:42Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![OvidiusCicero](https://avatars.discourse-cdn.com/v4/letter/o/73ab20/32.png) [@OvidiusCicero](https://discourse.julialang.org/u/OvidiusCicero)
#### Post date: [May 5, 2019, 11:22pm UTC](https://discourse.julialang.org/t/julia-function-performance-behaving-strange-when-combining-broadcasting-a-namedtuple-of-parameters-and-a-function-as-argument/23888/1 "2019-05-05T23:22:43Z")

</div>

I have the following simplified example taken from real code that calculates a function over a difference for a vector of inputs and a function input

```julia
params = (a=2,b=3) #
calc(p::NamedTuple, t) = p.a*t^2+p.b*t^3 # Example function

vec=[1:1000;]

testbroad1(p::NamedTuple, vec::Vector, calc::Function, t) = calc.((p,), t .- vec)

function testbroad2(params::NamedTuple, vec::Vector, calc::Function, t)
	c(t) = calc(params, t)
	c.(t.-vec)
end

```

When `testbroad1` and `testbroad2` are benachmarked, the following happens

```julia
julia> @btime testbroad1($params, $vec, $calc, 5.0)
  1.057 μs (5 allocations: 8.03 KiB)

julia> @btime testbroad2($params, $vec, $calc, 5.0)
  922.944 ns (1 allocation: 7.94 KiB)

```

`testbroad2` is faster by around 10%. In my more complex real world code the `testbroad1` takes the double time to finish (not benchmarking but around 8 seconds instead of 4)

1. Is that behavior expected or not?
2. What is the best way to achieve the above? It is absolutely essential for me that `params` and the function `calc` are passed as parameters to `testbroad` and the performance regression is not acceptable. Finding (the rather trivial) workaround has cost me couple of hours

---

<div class="post-metadata">

### Author: ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)
#### Post date: [May 6, 2019, 2:20am UTC](https://discourse.julialang.org/t/julia-function-performance-behaving-strange-when-combining-broadcasting-a-namedtuple-of-parameters-and-a-function-as-argument/23888/2 "2019-05-06T02:20:35Z")

</div>

I don’t fully understand the rules for this situation, but I know that Julia may not fully specialize on `::Function` arguments, in order to avoid potentially expensive recompilation (since every single function is a different type). Forcing Julia to specialize on that argument fixes the issue:

```julia
testbroad3(p::NamedTuple, vec::Vector, calc::F, t) where {F <: Function} = calc.((p,), t .- vec)

```

```julia
julia> @btime testbroad1($params, $vec, $calc, 5.0);
  1.038 μs (5 allocations: 8.03 KiB)

julia> @btime testbroad2($params, $vec, $calc, 5.0);
  899.103 ns (1 allocation: 7.94 KiB)

julia> @btime testbroad3($params, $vec, $calc, 5.0);
  883.857 ns (1 allocation: 7.94 KiB)

```

---

<div class="post-metadata">

### Author: ![OvidiusCicero](https://avatars.discourse-cdn.com/v4/letter/o/73ab20/32.png) [@OvidiusCicero](https://discourse.julialang.org/u/OvidiusCicero)
#### Post date: [May 6, 2019, 7:12am UTC](https://discourse.julialang.org/t/julia-function-performance-behaving-strange-when-combining-broadcasting-a-namedtuple-of-parameters-and-a-function-as-argument/23888/3 "2019-05-06T07:12:25Z")

</div>

thanks! That even kinda makes sense
