# Passing struct vs struct fields as function arguments

**URL:** <https://discourse.julialang.org/t/passing-struct-vs-struct-fields-as-function-arguments/67584>\
**Category:** Performance\
**Tags:** memory-allocation, data\_structures, struct\
**Created:** [September 2, 2021, 2:59pm UTC](https://discourse.julialang.org/t/passing-struct-vs-struct-fields-as-function-arguments/67584 "2021-09-02T14:59:09Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![fipelle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fipelle/32/4772_2.png) [@fipelle](https://discourse.julialang.org/u/fipelle)\
**Post date:** [September 2, 2021, 2:59pm UTC](https://discourse.julialang.org/t/passing-struct-vs-struct-fields-as-function-arguments/67584/1 "2021-09-02T14:59:09Z")

</div>

Hi,

I have noticed that passing struct fields as function arguments generally results in better performance compared to passing the struct directly. For instance,

```julia
using BenchmarkTools;
using Random;

struct MyStruct
    A::Vector{Float64}
    B::Matrix{Float64}
end

Random.seed!(1);
something = MyStruct(randn(100), randn(100,100));

function test1(A::Vector{Float64}, B::Matrix{Float64})
    return B*A;
end

call_test1(something::MyStruct) = test1(something.A, something.B);

function test2(something::MyStruct)
    return something.B*something.A;
end

@inline function test3(something::MyStruct)
    return something.B*something.A;
end

```

```julia
julia> @btime call_test1($something);
  2.331 μs (1 allocation: 896 bytes)

julia> @btime test2($something);
  2.517 μs (1 allocation: 896 bytes)

julia> @btime test3($something);
  2.598 μs (1 allocation: 896 bytes)

julia> @benchmark call_test1($something)
BenchmarkTools.Trial: 10000 samples with 9 evaluations.
 Range (min … max): 2.428 μs … 94.531 μs ┊ GC (min … max): 0.00% … 95.36%
 Time (median): 2.899 μs ┊ GC (median): 0.00%
 Time (mean ± σ): 2.978 μs ± 1.030 μs ┊ GC (mean ± σ): 0.30% ± 0.95%

          ▁▅▇█▃                                               
  ▁▂▄▅▆▆▅▆██████▆▆▆▆▅▃▂▂▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ ▂
  2.43 μs Histogram: frequency by time 4.86 μs <

 Memory estimate: 896 bytes, allocs estimate: 1.

julia> @benchmark test2($something)
BenchmarkTools.Trial: 10000 samples with 9 evaluations.
 Range (min … max): 2.664 μs … 95.310 μs ┊ GC (min … max): 0.00% … 95.29%
 Time (median): 3.091 μs ┊ GC (median): 0.00%
 Time (mean ± σ): 3.363 μs ± 1.503 μs ┊ GC (mean ± σ): 0.27% ± 0.95%

    ▂▇█▆▁                                                     
  ▁▃█████▅▃▂▂▂▂▂▃▃▂▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ ▂
  2.66 μs Histogram: frequency by time 7.51 μs <

 Memory estimate: 896 bytes, allocs estimate: 1.

julia> @benchmark test3($something)
BenchmarkTools.Trial: 10000 samples with 9 evaluations.
 Range (min … max): 2.379 μs … 97.867 μs ┊ GC (min … max): 0.00% … 96.19%
 Time (median): 3.214 μs ┊ GC (median): 0.00%
 Time (mean ± σ): 3.586 μs ± 1.513 μs ┊ GC (mean ± σ): 0.26% ± 0.96%

  ▁▃ ▃▆██▇▆▆▅▆▆▅▃▁ ▁▁▁▁ ▂
  █████████████████████████▇██▆▇██▇▆▇▇▇▆▇▆▇▆▇▇▆▇▆▆▆▆▆▆▆▆▆▆▅▅ █
  2.38 μs Histogram: log(frequency) by time 8.93 μs <

 Memory estimate: 896 bytes, allocs estimate: 1.

```

Can someone explain why? Any link to the appropriate documentation (if available) would be appreciated.

---

<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 2, 2021, 3:13pm UTC](https://discourse.julialang.org/t/passing-struct-vs-struct-fields-as-function-arguments/67584/2 "2021-09-02T15:13:12Z")

</div>

my two cents is that that is only benchmarking noise:

```julia
julia> @btime call_test1($something);
  2.614 μs (1 allocation: 896 bytes)

julia> @btime test2($something);
  2.808 μs (1 allocation: 896 bytes)

julia> @btime test3($something);
  2.821 μs (1 allocation: 896 bytes)

julia> @btime call_test1($something);
  2.805 μs (1 allocation: 896 bytes)

julia> @btime test2($something);
  2.879 μs (1 allocation: 896 bytes)

julia> @btime test3($something);
  2.765 μs (1 allocation: 896 bytes)

julia> @btime call_test1($something);
  2.735 μs (1 allocation: 896 bytes)

julia> @btime test2($something);
  3.511 μs (1 allocation: 896 bytes)

julia> @btime test3($something);
  3.441 μs (1 allocation: 896 bytes)

julia> @btime call_test1($something);
  3.692 μs (1 allocation: 896 bytes)

julia> @btime test2($something);
  2.986 μs (1 allocation: 896 bytes)

julia> @btime test3($something);
  3.778 μs (1 allocation: 896 bytes)

```

---

<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:** [September 2, 2021, 3:15pm UTC](https://discourse.julialang.org/t/passing-struct-vs-struct-fields-as-function-arguments/67584/3 "2021-09-02T15:15:16Z")

</div>

Yeah, I get exactly the same performance for all three:

```julia
julia> @btime call_test1($something);
  2.579 μs (1 allocation: 896 bytes)

julia> @btime test2($something);
  2.525 μs (1 allocation: 896 bytes)

julia> @btime test3($something);
  2.552 μs (1 allocation: 896 bytes)

```

which makes sense–I wouldn’t expect there to be any difference.

---

<div class="post-metadata">

**Author:** ![fipelle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fipelle/32/4772_2.png) [@fipelle](https://discourse.julialang.org/u/fipelle)\
**Post date:** [September 2, 2021, 3:21pm UTC](https://discourse.julialang.org/t/passing-struct-vs-struct-fields-as-function-arguments/67584/4 "2021-09-02T15:21:40Z")

</div>

Thank you both. I agree with you, I was not expecting to find any differences. However, running many times `@btime` I keep getting the output I posted above (in relative terms). Can it be something specific to my laptop?

---

<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:** [September 2, 2021, 3:43pm UTC](https://discourse.julialang.org/t/passing-struct-vs-struct-fields-as-function-arguments/67584/5 "2021-09-02T15:43:18Z")

</div>

`@btime` reports the minimal time - under load, your laptop may throttle its speed, making your benchmark appear slower. Since your timings seem to get slower and slower, I’d guess during the first benchmark the CPU is running with a higher clockspeed than with subsequent benchmarks.

What CPU do you have?

---

<div class="post-metadata">

**Author:** ![fipelle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fipelle/32/4772_2.png) [@fipelle](https://discourse.julialang.org/u/fipelle)\
**Post date:** [September 2, 2021, 4:01pm UTC](https://discourse.julialang.org/t/passing-struct-vs-struct-fields-as-function-arguments/67584/6 "2021-09-02T16:01:36Z")

</div>

Thanks. I have an Intel(R) Core™ i7-1060NG7 CPU @ 1.20GHz.
