# Strange allocation in closure

**URL:** <https://discourse.julialang.org/t/strange-allocation-in-closure/104017>\
**Category:** Performance\
**Tags:** memory-allocation, closure\
**Created:** [September 19, 2023, 9:15am UTC](https://discourse.julialang.org/t/strange-allocation-in-closure/104017 "2023-09-19T09:15:10Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![trahflow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/trahflow/32/30585_2.png) [@trahflow](https://discourse.julialang.org/u/trahflow)\
**Post date:** [September 19, 2023, 9:15am UTC](https://discourse.julialang.org/t/strange-allocation-in-closure/104017/1 "2023-09-19T09:15:10Z")

</div>

Hi,

I observe an allocation involving a closure that I do not understand.  
Consider the following minimal working example:

```julia
julia> function outer(a)
           inner(b, c) = b, c
           a, inner
       end
outer (generic function with 1 method)

julia> a, inner = outer(5)
(5, inner)

julia> @allocations outer(5)
0

julia> inner(5, 8)
(5, 8)

julia> @allocations inner(5, 8)
1

julia> @allocated inner(5, 8)
32

```

Note that `inner()` doesn’t really close over anything. Output of `@code_warntype` of both, `outer(5)` and `inner(5, 8)` looks fine.  
Is this a false positive of the `@allocated` macro?

> **versioninfo**
>
> ```julia
> julia> versioninfo()
> Julia Version 1.9.3
> Commit bed2cd540a1 (2023-08-24 14:43 UTC)
> Build Info:
> Official https://julialang.org/ release
> Platform Info:
> OS: Linux (x86_64-linux-gnu)
> CPU: 8 × 11th Gen Intel(R) Core(TM) i5-1145G7 @ 2.60GHz
> WORD_SIZE: 64
> LIBM: libopenlibm
> LLVM: libLLVM-14.0.6 (ORCJIT, tigerlake)
> Threads: 1 on 8 virtual cores
> 
> ```

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [September 19, 2023, 9:27am UTC](https://discourse.julialang.org/t/strange-allocation-in-closure/104017/2 "2023-09-19T09:27:19Z")

</div>

> [@trahflow](#):
>
> ```julia
> julia> a, inner = outer(5)
> (5, inner)
> 
> ```

When you do this step, you bound `inner` to a untyped global variable. That’s the source of the allocation.

Here’s an example where it’s bound to a local variable and you can see there’s no allocation:

```julia
julia> function outer(a)
           inner(b, c) = b, c
           a, inner
       end;

julia> let (a, inner) = outer(5)
           @allocated inner(5, 8)
       end
0

```

---

<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:** [September 19, 2023, 9:28am UTC](https://discourse.julialang.org/t/strange-allocation-in-closure/104017/3 "2023-09-19T09:28:50Z")

</div>

Seems like a false-positive (but I don’t understand how these come about).  
The generated assembly is identical for

```julia
julia> f(a,b) = return a,b
julia> @code_native inner(5,8)
julia> @code_native f(5,8) # identical output to above

```

and the latter shows no allocations.

Edit: @Mason above explained where the allocation comes from.

---

<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:** [September 19, 2023, 2:41pm UTC](https://discourse.julialang.org/t/strange-allocation-in-closure/104017/4 "2023-09-19T14:41:18Z")

</div>

This makes it very explicit:

```julia
julia> function outer(a)
           inner(b, c) = b, c
           a, inner
       end;

julia> a, unstable_inner = outer(5)
(5, var"#inner#1"())

julia> const inner = unstable_inner
inner (generic function with 1 method)

julia> @allocated unstable_inner(5,8)
27728

julia> @allocated inner(5,8)
0

```
