# FunctionWrapper allocating when called

**URL:** <https://discourse.julialang.org/t/functionwrapper-allocating-when-called/119854>\
**Category:** Performance\
**Created:** [September 25, 2024, 10:13am UTC](https://discourse.julialang.org/t/functionwrapper-allocating-when-called/119854 "2024-09-25T10:13:28Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![Goncalo\_Pena](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/goncalo_pena/32/51291_2.png) [@Goncalo\_Pena](https://discourse.julialang.org/u/Goncalo_Pena)\
**Post date:** [September 25, 2024, 10:13am UTC](https://discourse.julialang.org/t/functionwrapper-allocating-when-called/119854/1 "2024-09-25T10:13:28Z")

</div>

I made the following test code to check some allocations going around while using FunctionWrappers on a piece of code I have.

```julia
using FunctionWrappers
import FunctionWrappers: FunctionWrapper
using BenchmarkTools

T = Float64
f(x) = x[1]*x[2]

wrapf = FunctionWrapper{T, Tuple{Tuple{T,T}}}(f)
p = (1.0, 2.0)
wrapf(p)
@btime wrapf($p)
# 39.650 ns (2 allocations: 48 bytes)

```

I’m trying to figure out where these 2 allocations come from, but I’m unaware of what the issue is.

---

<div class="post-metadata">

**Author:** ![DanielVandH](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielvandh/32/31134_2.png) [@DanielVandH](https://discourse.julialang.org/u/DanielVandH)\
**Post date:** [September 25, 2024, 10:14am UTC](https://discourse.julialang.org/t/functionwrapper-allocating-when-called/119854/2 "2024-09-25T10:14:24Z")

</div>

```julia
julia> @btime $wrapf($p)
  8.400 ns (0 allocations: 0 bytes)
2.0

```

You need to also do `$` on `wrapf`.

---

<div class="post-metadata">

**Author:** ![Goncalo\_Pena](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/goncalo_pena/32/51291_2.png) [@Goncalo\_Pena](https://discourse.julialang.org/u/Goncalo_Pena)\
**Post date:** [September 25, 2024, 10:22am UTC](https://discourse.julialang.org/t/functionwrapper-allocating-when-called/119854/3 "2024-09-25T10:22:33Z")

</div>

Shouldn’t I only be interpolating the input variables? Is the `$` in wrap needed because the function returns a value?

---

<div class="post-metadata">

**Author:** ![DanielVandH](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielvandh/32/31134_2.png) [@DanielVandH](https://discourse.julialang.org/u/DanielVandH)\
**Post date:** [September 25, 2024, 10:29am UTC](https://discourse.julialang.org/t/functionwrapper-allocating-when-called/119854/4 "2024-09-25T10:29:52Z")

</div>

It’s for interpolating variables into the expression - `wrapf` is its own variable. If it was a `const`, it’d be fine:

```julia
julia> const _wrapf = wrapf
FunctionWrapper{Float64, Tuple{Tuple{Float64, Float64}}}(Ptr{Nothing} @0x0000016e4563e250, Ptr{Nothing} @0x0000016e44170030, Base.RefValue{typeof(f)}(f), typeof(f))

julia> @btime _wrapf($p)
  8.200 ns (0 allocations: 0 bytes)
2.0

```

---

<div class="post-metadata">

**Author:** ![Goncalo\_Pena](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/goncalo_pena/32/51291_2.png) [@Goncalo\_Pena](https://discourse.julialang.org/u/Goncalo_Pena)\
**Post date:** [September 25, 2024, 10:47am UTC](https://discourse.julialang.org/t/functionwrapper-allocating-when-called/119854/5 "2024-09-25T10:47:40Z")

</div>

Well, that makes sense. However, if I wrap the code in a function, I think I should be free of that extra allocation but it still remains.

```julia
function main()
	T = Float64
	f(x) = x[1] * x[2]

	wrapf = FunctionWrapper{T,Tuple{Tuple{T,T}}}(f)
	p = (1.0, 2.0)
	x = wrapf(p)
	return nothing
end

@btime main()

```

---

<div class="post-metadata">

**Author:** ![DanielVandH](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielvandh/32/31134_2.png) [@DanielVandH](https://discourse.julialang.org/u/DanielVandH)\
**Post date:** [September 25, 2024, 10:56am UTC](https://discourse.julialang.org/t/functionwrapper-allocating-when-called/119854/6 "2024-09-25T10:56:24Z")

</div>

Because `FunctionWrapper` seems to allocate.

```julia
julia> function main()
           T = Float64
           f(x) = x[1] * x[2]
           wrapf = FunctionWrapper{T,Tuple{Tuple{T,T}}}(f)
       end
main (generic function with 1 method)

julia> @benchmark main()
BenchmarkTools.Trial: 10000 samples with 1000 evaluations.
 Range (min … max): 7.900 ns … 601.800 ns ┊ GC (min … max): 0.00% … 0.00%
 Time (median): 21.800 ns ┊ GC (median): 0.00%
 Time (mean ± σ): 25.099 ns ± 12.977 ns ┊ GC (mean ± σ): 0.00% ± 0.00%

             ▆█
  ▃▃▁▁▁▁▁▁▁▃████▇▅▅▅▄▄▄▃▃▃▂▂▂▂▂▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ ▂
  7.9 ns Histogram: frequency by time 69.9 ns <

 Memory estimate: 56 bytes, allocs estimate: 2.

```

---

<div class="post-metadata">

**Author:** ![gdalle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdalle/32/27854_2.png) [@gdalle](https://discourse.julialang.org/u/gdalle)\
**Post date:** [September 25, 2024, 2:23pm UTC](https://discourse.julialang.org/t/functionwrapper-allocating-when-called/119854/7 "2024-09-25T14:23:48Z")

</div>

I think this might be because you’re passing the type `T` as an object and Julia avoids specializing on it. If you try `main(::Type{T}) where {T}` the results could be different?  
[https://docs.julialang.org/en/v1/manual/performance-tips/#Be-aware-of-when-Julia-avoids-specializing](https://docs.julialang.org/en/v1/manual/performance-tips/#Be-aware-of-when-Julia-avoids-specializing)

---

<div class="post-metadata">

**Author:** ![Goncalo\_Pena](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/goncalo_pena/32/51291_2.png) [@Goncalo\_Pena](https://discourse.julialang.org/u/Goncalo_Pena)\
**Post date:** [September 25, 2024, 3:04pm UTC](https://discourse.julialang.org/t/functionwrapper-allocating-when-called/119854/8 "2024-09-25T15:04:11Z")

</div>

The allocations remain even with `::Type{T}`.

I have also tried with some of the examples in FunctionWrappers.jl’s tests and they have the same allocation behaviour. It seems there are always allocations when the wrapper is created.

---

<div class="post-metadata">

**Author:** ![DanielVandH](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielvandh/32/31134_2.png) [@DanielVandH](https://discourse.julialang.org/u/DanielVandH)\
**Post date:** [September 25, 2024, 4:06pm UTC](https://discourse.julialang.org/t/functionwrapper-allocating-when-called/119854/9 "2024-09-25T16:06:01Z")

</div>

Since `T` is defined in the body as a constant value I don’t think that applies here. Looking at `@code_llvm` it seems to know to define `double`s in either case.

---

<div class="post-metadata">

**Author:** ![danielwe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielwe/32/35657_2.png) [@danielwe](https://discourse.julialang.org/u/danielwe)\
**Post date:** [September 26, 2024, 1:18am UTC](https://discourse.julialang.org/t/functionwrapper-allocating-when-called/119854/10 "2024-09-26T01:18:15Z")

</div>

A FunctionWrapper is a mutable struct with two untyped fields. There’s probably no way to avoid a few allocations when instantiating one. See [FunctionWrappers.jl/src/FunctionWrappers.jl at 3a579da1e5080d4563b6e819f88f4525aff4f45d · yuyichao/FunctionWrappers.jl · GitHub](https://github.com/yuyichao/FunctionWrappers.jl/blob/3a579da1e5080d4563b6e819f88f4525aff4f45d/src/FunctionWrappers.jl#L75-L86)

---

<div class="post-metadata">

**Author:** ![Goncalo\_Pena](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/goncalo_pena/32/51291_2.png) [@Goncalo\_Pena](https://discourse.julialang.org/u/Goncalo_Pena)\
**Post date:** [September 26, 2024, 12:52pm UTC](https://discourse.julialang.org/t/functionwrapper-allocating-when-called/119854/11 "2024-09-26T12:52:50Z")

</div>

Thank you all for your i put. I think yhese are allocations to live with.

I took a look at some SciML code where these wrappers are used and got to the conclusion that they are used of, say, a ODEProblem, and one just pays the allocation cost once.
