# Memory allocation in member extraction from a struct?

**URL:** <https://discourse.julialang.org/t/memory-allocation-in-member-extraction-from-a-struct/2158>\
**Category:** General Usage\
**Tags:** question\
**Created:** [February 17, 2017, 8:18pm UTC](https://discourse.julialang.org/t/memory-allocation-in-member-extraction-from-a-struct/2158 "2017-02-17T20:18:16Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![dmbates](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dmbates/32/44_2.png) [@dmbates](https://discourse.julialang.org/u/dmbates)\
**Post date:** [February 17, 2017, 8:18pm UTC](https://discourse.julialang.org/t/memory-allocation-in-member-extraction-from-a-struct/2158/1 "2017-02-17T20:18:16Z")

</div>

A common idiom for me when operating on a struct is to assign local names for members of the struct. That is, if the argument is `A` with members `foo`, `bar`, and `baz` I often begin a method with

```nohighlight
function myfunc(A)
    foo, bar, baz = A.foo, A.bar, A.baz
    ...
    A
end

```

The purpose is to avoid repeated extraction (the compiler may optimize it away but I don’t think that is a certainty) and to make the code somewhat cleaner.

I notice when checking allocations with `--track-allocations` that there is apparently a considerable amount of allocation at those lines. Am I shooting myself in the foot by doing this? I was under the impression that this would just assign some pointers or, at worst, scalars in the evaluation frame of the method.

Is it best to avoid assigning a tuple when doing this?

I have only tested in version 0.5.0 - my package has dependencies that are not satisfied in 0.6.0-dev yet.

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [February 17, 2017, 8:45pm UTC](https://discourse.julialang.org/t/memory-allocation-in-member-extraction-from-a-struct/2158/2 "2017-02-17T20:45:05Z")

</div>

An easy way to do this is to use the `@unpack` macro from Parameters.jl

> **[GitHub - mauro3/Parameters.jl: Types with default field values, keyword...](https://github.com/mauro3/Parameters.jl)**
>
> Types with default field values, keyword constructors and (un-)pack macros - GitHub - mauro3/Parameters.jl: Types with default field values, keyword constructors and (un-)pack macros

I never found performance issues by doing it.

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [February 17, 2017, 9:08pm UTC](https://discourse.julialang.org/t/memory-allocation-in-member-extraction-from-a-struct/2158/3 "2017-02-17T21:08:28Z")

</div>

Tuples of non `isbits` types are allocated on the stack (edit: I mean heap) so unless the compiler elides it, it is possible that is what you are seeing.

---

<div class="post-metadata">

**Author:** ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)\
**Post date:** [February 17, 2017, 10:09pm UTC](https://discourse.julialang.org/t/memory-allocation-in-member-extraction-from-a-struct/2158/4 "2017-02-17T22:09:33Z")

</div>

In Parameters.jl I “write it out” (I think I did this to avoid the problem @kristoffer.carlsson mentions):

```julia
julia> using Parameters

julia> macroexpand(:(@unpack a, b, c = d))
quote # /home/mauro/.julia/v0.5/Parameters/src/Parameters.jl, line 559:
    ##270 = d # /home/mauro/.julia/v0.5/Parameters/src/Parameters.jl, line 560:
    begin 
        a = Parameters.unpack(##270,Val{:a}())
        b = Parameters.unpack(##270,Val{:b}())
        c = Parameters.unpack(##270,Val{:c}())
    end # /home/mauro/.julia/v0.5/Parameters/src/Parameters.jl, line 561:
    ##270
end

```

@dmbates, does writing it out help in your case?

---

<div class="post-metadata">

**Author:** ![fengyang.wang](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fengyang.wang/32/104_2.png) [@fengyang.wang](https://discourse.julialang.org/u/fengyang.wang)\
**Post date:** [February 17, 2017, 10:12pm UTC](https://discourse.julialang.org/t/memory-allocation-in-member-extraction-from-a-struct/2158/5 "2017-02-17T22:12:19Z")

</div>

minor typo: I believe you mean “heap” instead of “stack” here.

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [February 17, 2017, 10:13pm UTC](https://discourse.julialang.org/t/memory-allocation-in-member-extraction-from-a-struct/2158/6 "2017-02-17T22:13:35Z")

</div>

Yes, thank you.

---

<div class="post-metadata">

**Author:** ![dmbates](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dmbates/32/44_2.png) [@dmbates](https://discourse.julialang.org/u/dmbates)\
**Post date:** [February 17, 2017, 11:00pm UTC](https://discourse.julialang.org/t/memory-allocation-in-member-extraction-from-a-struct/2158/7 "2017-02-17T23:00:18Z")

</div>

It doesn’t seem to make a difference if I expand the tuple assignment to separate assignments.

The exercise was worthwhile as I did find a section of the code that was allocating a huge amount of memory unnecessarily, which is the whole point of the JuliaCI group, whom I thank for their efforts.

---

<div class="post-metadata">

**Author:** ![johnmyleswhite](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/johnmyleswhite/32/31_2.png) [@johnmyleswhite](https://discourse.julialang.org/u/johnmyleswhite)\
**Post date:** [February 17, 2017, 11:37pm UTC](https://discourse.julialang.org/t/memory-allocation-in-member-extraction-from-a-struct/2158/8 "2017-02-17T23:37:28Z")

</div>

> [@dmbates](#):
>
> It doesn’t seem to make a difference if I expand the tuple assignment to separate assignments.

I worry that returning a tuple in the first place might force an extra allocation when the elements are not `isbits`:

```julia
julia> using BenchmarkTools

julia> function no_tuple()
           x = rand(100)
           return x
       end
no_tuple (generic function with 1 method)

julia> function yes_tuple()
           x = rand(100)
           return (x, )
       end
yes_tuple (generic function with 1 method)

julia> @benchmark no_tuple();

julia> @benchmark yes_tuple();

julia> @benchmark no_tuple()
BenchmarkTools.Trial:
  memory estimate: 896.00 bytes
  allocs estimate: 1
  --------------
  minimum time: 194.274 ns (0.00% GC)
  median time: 314.712 ns (0.00% GC)
  mean time: 531.899 ns (4.62% GC)
  maximum time: 119.999 μs (0.00% GC)
  --------------
  samples: 10000
  evals/sample: 685
  time tolerance: 5.00%
  memory tolerance: 1.00%

julia> @benchmark yes_tuple()
BenchmarkTools.Trial:
  memory estimate: 912.00 bytes
  allocs estimate: 2
  --------------
  minimum time: 202.074 ns (0.00% GC)
  median time: 309.267 ns (0.00% GC)
  mean time: 374.682 ns (8.69% GC)
  maximum time: 28.957 μs (0.00% GC)
  --------------
  samples: 10000
  evals/sample: 580
  time tolerance: 5.00%
  memory tolerance: 1.00%

```
