# Allocations on field access even though no abstract types are involved

**URL:** <https://discourse.julialang.org/t/allocations-on-field-access-even-though-no-abstract-types-are-involved/126672>\
**Category:** General Usage\
**Created:** [March 7, 2025, 11:06am UTC](https://discourse.julialang.org/t/allocations-on-field-access-even-though-no-abstract-types-are-involved/126672 "2025-03-07T11:06:22Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![nilsbecker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nilsbecker/32/12157_2.png) [@nilsbecker](https://discourse.julialang.org/u/nilsbecker)\
**Post date:** [March 7, 2025, 11:06am UTC](https://discourse.julialang.org/t/allocations-on-field-access-even-though-no-abstract-types-are-involved/126672/1 "2025-03-07T11:06:22Z")

</div>

Hi, after reading the [manual](https://docs.julialang.org/en/v1/manual/performance-tips/#Avoid-fields-with-abstract-containers), I was thinking to avoid dynamic lookup by parametrizing my type for a function with attached data, like so:

Original type:

```julia
struct FunctionWithExtra{A}
    f::A
    extra
end

```

where `f` is supposed to be a function called in a hot loop.

```julia
fwe = FunctionWithExtra(x -> (x*x; nothing), "some other info")
for i in 1:1.0:1000
    fwe.f(i)
end

```

Although the field `f` is now concretely typed, this allocates,

```julia
@allocated fwe.f(3.)

```

I then tried

```julia
struct FunctionBare{A}
    f::A
end
fbare = FunctionBare(x->(x*x; nothing))
fbare.f(2.)
@allocated fbare.f(2.)

```

which as expected does not allocate, but does not give me the extra attached  
functionality I want.

But even this

```julia
struct FunctionWithConcreteExtra{A}
    f::A
    extra::Int64
end
fwce = FunctionWithConcreteExtra(x ->(x*x; nothing), 34)
fwce.f(2.)
@allocated fwce.f(2.)

```

does allocate.

How can I make a wrapped function type that does not allocate on field access? In my actual code, there is a whole collection of “extras” with diverse abstract types, so I think it’s not great to try and parametrize them all?

---

<div class="post-metadata">

**Author:** ![BdeKoning](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bdekoning/32/214557_2.png) [@BdeKoning](https://discourse.julialang.org/u/BdeKoning)\
**Post date:** [March 7, 2025, 11:12am UTC](https://discourse.julialang.org/t/allocations-on-field-access-even-though-no-abstract-types-are-involved/126672/2 "2025-03-07T11:12:53Z")

</div>

[JuliaLang/FunctionWrappers.jl: Type stable and efficient wrapper of arbitrary Julia functions](https://github.com/JuliaLang/FunctionWrappers.jl)

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [March 7, 2025, 11:19am UTC](https://discourse.julialang.org/t/allocations-on-field-access-even-though-no-abstract-types-are-involved/126672/3 "2025-03-07T11:19:15Z")

</div>

Are you certain that it’s the _field access_ and not the retrieval of the non-`const` global variable `fw` that allocates?

---

<div class="post-metadata">

**Author:** ![nilsbecker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nilsbecker/32/12157_2.png) [@nilsbecker](https://discourse.julialang.org/u/nilsbecker)\
**Post date:** [March 7, 2025, 11:57am UTC](https://discourse.julialang.org/t/allocations-on-field-access-even-though-no-abstract-types-are-involved/126672/4 "2025-03-07T11:57:07Z")

</div>

@Sukera I think it’s the field access, because otherwise `fbare` should also allocate, no?

@BdeKoning To me that reads like it ensures type stability in presence of callable fields. From another [thread](https://discourse.julialang.org/t/function-inside-struct-allocates-when-referenced/105785/4) I picked up the technique to parametrize the struct on the type of the function, `FunctionWithExtra{A}` for example, which gives a concrete type to the struct. This works to avoid alloction with `FunctionBare`, for example. Also,

```julia
julia> typeof(fwe)
FunctionWithExtra{var"#112#113"}

```

appears to have a concrete type. Am I mistaken?

---

<div class="post-metadata">

**Author:** ![nilsbecker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nilsbecker/32/12157_2.png) [@nilsbecker](https://discourse.julialang.org/u/nilsbecker)\
**Post date:** [March 7, 2025, 12:04pm UTC](https://discourse.julialang.org/t/allocations-on-field-access-even-though-no-abstract-types-are-involved/126672/5 "2025-03-07T12:04:53Z")

</div>

Here is a surprising (to me) workaround:

```julia
(fwe::FunctionWithExtra)(arg) = fwe.f(arg)
@allocated fwe.f(4.) # gives 16
fwe(4.)
@allocated fwe(4.) # gives 0 

```

confusing, but maybe workable for my use case.

---

<div class="post-metadata">

**Author:** ![sdanisch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sdanisch/32/1406_2.png) [@sdanisch](https://discourse.julialang.org/u/sdanisch)\
**Post date:** [March 7, 2025, 12:58pm UTC](https://discourse.julialang.org/t/allocations-on-field-access-even-though-no-abstract-types-are-involved/126672/6 "2025-03-07T12:58:43Z")

</div>

It’s doing things in global scope I’d say:

```julia
test(x) = x.f(3.0)
@allocated test(fwe) == 0

```

---

<div class="post-metadata">

**Author:** ![nilsbecker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nilsbecker/32/12157_2.png) [@nilsbecker](https://discourse.julialang.org/u/nilsbecker)\
**Post date:** [March 7, 2025, 1:06pm UTC](https://discourse.julialang.org/t/allocations-on-field-access-even-though-no-abstract-types-are-involved/126672/7 "2025-03-07T13:06:16Z")

</div>

I stumbled on that as well, so I have been rewriting my loops like this:

```julia
fwe = FunctionWithExtra(x -> (x*x; nothing), "some other info")
fwrap = fwe.f
for i in 1:1.0:1000
    fwrap(i)
end

```

which also avoided allocations in the loop. But it feels very clunky.

EDIT: I didn’t get what you showed at first. Now I do.

---

<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:** [March 7, 2025, 1:07pm UTC](https://discourse.julialang.org/t/allocations-on-field-access-even-though-no-abstract-types-are-involved/126672/8 "2025-03-07T13:07:27Z")

</div>

> [@nilsbecker](#):
>
> @Sukera I think it’s the field access, because otherwise `fbare` should also allocate, no?

It’s not the field access, @Sukera is correct. `fwe` is a non-constant global variable, so calling it allocates.

```julia
julia> struct FunctionWithExtra{A}
           f::A
           extra
       end

julia> fwe = FunctionWithExtra(x -> (x*x; nothing), "some other info");

julia> fwe.f(1.0); # get complation out of the way

julia> @allocated fwe.f(1.0)
16

julia> let f = fwe.f
           @allocated f(3.0)
       end
0

```

The `fbare` version doesn’t allocate because `fbare` is an `isbits` type.

---

<div class="post-metadata">

**Author:** ![nilsbecker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nilsbecker/32/12157_2.png) [@nilsbecker](https://discourse.julialang.org/u/nilsbecker)\
**Post date:** [March 7, 2025, 1:11pm UTC](https://discourse.julialang.org/t/allocations-on-field-access-even-though-no-abstract-types-are-involved/126672/9 "2025-03-07T13:11:32Z")

</div>

Ah, learned something new. So all of this is a red herring? If I define `fwe` inside a function and later call `fwe.f(x)` that will be fine, yes?

---

<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:** [March 7, 2025, 1:12pm UTC](https://discourse.julialang.org/t/allocations-on-field-access-even-though-no-abstract-types-are-involved/126672/10 "2025-03-07T13:12:18Z")

</div>

Yes, that’s what @sdanisch showed.
