# Is simply accessing an array element really allocating? (Solved)

**URL:** <https://discourse.julialang.org/t/is-simply-accessing-an-array-element-really-allocating-solved/20311>\
**Category:** New to Julia\
**Created:** [January 31, 2019, 2:02pm UTC](https://discourse.julialang.org/t/is-simply-accessing-an-array-element-really-allocating-solved/20311 "2019-01-31T14:02:37Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![robsmith11](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/robsmith11/32/29641_2.png) [@robsmith11](https://discourse.julialang.org/u/robsmith11)\
**Post date:** [January 31, 2019, 2:02pm UTC](https://discourse.julialang.org/t/is-simply-accessing-an-array-element-really-allocating-solved/20311/1 "2019-01-31T14:02:37Z")

</div>

I’m still trying to understand when Julia code triggers allocations. Is the example below really allocating? If so, why? Or is the measurement incorrect?

```julia
julia> a = [1.0];

julia> function f(x)
       x[1]
       end
f (generic function with 1 method)

julia> @btime f(a)
  14.635 ns (1 allocation: 16 bytes)
1.0

julia> @allocated f(a)
16

julia> @code_native f(a)
        .text
; â”Œ @ REPL[13]:2 within `f'
; â”‚â”Œ @ REPL[13]:2 within `getindex'
        movq (%rdi), %rax
        vmovsd (%rax), %xmm0 # xmm0 = mem[0],zero
; â”‚â””
        retq
        nopl (%rax,%rax)
; â””

```

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [January 31, 2019, 2:11pm UTC](https://discourse.julialang.org/t/is-simply-accessing-an-array-element-really-allocating-solved/20311/2 "2019-01-31T14:11:20Z")

</div>

The function returns a value which must be allocated: the returned value is 8 bytes and a type tag for it is 8 bytes. However if this is used in a context where the value doesn’t have to be returned or its use can be inlined then no allocation needs to happen.

---

<div class="post-metadata">

**Author:** ![swt30](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/swt30/32/4667_2.png) [@swt30](https://discourse.julialang.org/u/swt30)\
**Post date:** [January 31, 2019, 2:15pm UTC](https://discourse.julialang.org/t/is-simply-accessing-an-array-element-really-allocating-solved/20311/3 "2019-01-31T14:15:43Z")

</div>

If you interpolate the global variable `a` into the benchmarking expression, `@btime` shows no allocation:

```nohighlight
julia> @btime f($a)
  1.495 ns (0 allocations: 0 bytes)
1.0

```

---

<div class="post-metadata">

**Author:** ![robsmith11](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/robsmith11/32/29641_2.png) [@robsmith11](https://discourse.julialang.org/u/robsmith11)\
**Post date:** [January 31, 2019, 2:15pm UTC](https://discourse.julialang.org/t/is-simply-accessing-an-array-element-really-allocating-solved/20311/4 "2019-01-31T14:15:50Z")

</div>

> [@StefanKarpinski](#):
>
> The function returns a value which must be allocated: the returned value is 8 bytes and a type tag for it is 8 bytes. However if this is used in a context where the value doesn’t have to be returned or its use can be inlined then no allocation needs to happen.

So why doesn’t every function that returns a value report an allocation when measured in the REPL?

For example, if I change the example above from `Vector{Float64}` to `Vector{Int64}`, then it reports zero allocations.

---

<div class="post-metadata">

**Author:** ![robsmith11](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/robsmith11/32/29641_2.png) [@robsmith11](https://discourse.julialang.org/u/robsmith11)\
**Post date:** [January 31, 2019, 2:17pm UTC](https://discourse.julialang.org/t/is-simply-accessing-an-array-element-really-allocating-solved/20311/5 "2019-01-31T14:17:12Z")

</div>

> [@swt30](#):
>
> If you interpolate the global variable `a` into the benchmarking expression, `@btime` shows no allocation:

Ahh… that’s right. I forgot about interpolation. Thanks!

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [January 31, 2019, 2:28pm UTC](https://discourse.julialang.org/t/is-simply-accessing-an-array-element-really-allocating-solved/20311/6 "2019-01-31T14:28:29Z")

</div>

There’s a cache of small integer objects. If you return a larger integer value you’ll see that allocation is required again.

---

<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:** [January 31, 2019, 2:30pm UTC](https://discourse.julialang.org/t/is-simply-accessing-an-array-element-really-allocating-solved/20311/7 "2019-01-31T14:30:45Z")

</div>

> [@StefanKarpinski](#):
>
> There’s a cache of small integer objects.

This returns a float though? And also

```julia
julia> const a = [100000000000]
1-element Array{Int64,1}:
 100000000000

julia> function f(x)
           x[1]
       end;

julia> @allocated f(a)
0

```

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [January 31, 2019, 2:40pm UTC](https://discourse.julialang.org/t/is-simply-accessing-an-array-element-really-allocating-solved/20311/8 "2019-01-31T14:40:39Z")

</div>

> [@kristoffer.carlsson](#):
>
> This returns a float though?

> [@robsmith11](#):
>
> For example, if I change the example above from `Vector{Float64}` to `Vector{Int64}` , then it reports zero allocations.

> [@kristoffer.carlsson](#):
>
> const a = [100000000000]

Yes, that’s an excellent riddle. Seems to have something to do with the `const` 😄.

The moral of the story is: `@allocated` does not lie, it reports what Julia actually allocates; what Julia actually does may be trickier than you think, but it’s not worth sweating a few tens of bytes here and there unless you _want_ to go down a rabbit hole.

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [January 31, 2019, 2:54pm UTC](https://discourse.julialang.org/t/is-simply-accessing-an-array-element-really-allocating-solved/20311/9 "2019-01-31T14:54:25Z")

</div>

This is entirely to do with how BenchmarkTools treats expressions and global variables.

When you don’t interpolate and just ask for `@btime f(a)`, then BenchmarkTools is measuring the performance as though you wrote `f(a)` directly inside some function. Note, though that `a` is a _global_ and it’s not a constant — so this is a type instability! When you flag `a` by interpolating it with a `$`, then BenchmarkTools treats it as though it were an _argument_ to that function. It becomes a type-stable local variable in the benchmarking loop.

So then you can see the extra optimization we have for small integers in such a type-unstable case. It doesn’t show up in Kristoffer’s experiment above because he made his global a `const` (so it’s no longer type-unstable) and tested it with `@allocated`, which works differently and wouldn’t show a type-instability in the arguments.

```julia
julia> a = [1.0]
1-element Array{Float64,1}:
 1.0

julia> @btime f(a)
  35.767 ns (1 allocation: 16 bytes)
1.0

julia> @btime f($a)
  2.077 ns (0 allocations: 0 bytes)
1.0

julia> a = [1]
1-element Array{Int64,1}:
 1

julia> @btime f(a)
  26.699 ns (0 allocations: 0 bytes)
1

julia> @btime f($a)
  2.077 ns (0 allocations: 0 bytes)
1

julia> a = [1000000]
1-element Array{Int64,1}:
 1000000

julia> @btime f(a)
  36.426 ns (1 allocation: 16 bytes)
1000000

julia> @btime f($a)
  2.077 ns (0 allocations: 0 bytes)
1000000

```
