# Are the entries in a vector of immutable structs stored in place, or is there always a pointer to the heap?

**URL:** <https://discourse.julialang.org/t/are-the-entries-in-a-vector-of-immutable-structs-stored-in-place-or-is-there-always-a-pointer-to-the-heap/33141>\
**Category:** Performance\
**Created:** [January 9, 2020, 9:25am UTC](https://discourse.julialang.org/t/are-the-entries-in-a-vector-of-immutable-structs-stored-in-place-or-is-there-always-a-pointer-to-the-heap/33141 "2020-01-09T09:25:40Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![Sean\_Matthews](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sean_matthews/32/8206_2.png) [@Sean\_Matthews](https://discourse.julialang.org/u/Sean_Matthews)\
**Post date:** [January 9, 2020, 9:25am UTC](https://discourse.julialang.org/t/are-the-entries-in-a-vector-of-immutable-structs-stored-in-place-or-is-there-always-a-pointer-to-the-heap/33141/1 "2020-01-09T09:25:40Z")

</div>

Are the entries in a vector of immutable structs stored in place, or  
is there always a pointer to the heap?

(Or how can I get Julia to do something equivalent).

I have a question about the interplay between vectors and  
mutable/immutable structs.

If I have a vector of mutable structs, then obviously then each entry  
in the vector has an independent life in the heap (since the same  
object could be in more than one vector, and if I modify a struct  
stored in one vector I can see the modifications in another vector).

On the other hand, if I have a vector of immutable structs (of  
well-defined size), then there is no need for a pointer to an  
independent object - I can store the contents of the struct _in_  
_situ_. There is no need for independent allocation on the heap.

The question is: does Julia do this, or is there some way to get the  
same effect, so that when I push structured but immutable data onto a  
vector, it is written into the vector in the same way as if I were to  
push an integer onto a vector of integers, and not linked via a  
pointer.

Motivation is obviously to avoid allocating heap storage every time I  
push a structured something onto a vector.

Thanks,

Sean Matthews

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [January 9, 2020, 12:47pm UTC](https://discourse.julialang.org/t/are-the-entries-in-a-vector-of-immutable-structs-stored-in-place-or-is-there-always-a-pointer-to-the-heap/33141/2 "2020-01-09T12:47:23Z")

</div>

> [@Sean\_Matthews](#):
>
> Are the entries in a vector of immutable structs stored in place

Yes.

---

<div class="post-metadata">

**Author:** ![Sean\_Matthews](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sean_matthews/32/8206_2.png) [@Sean\_Matthews](https://discourse.julialang.org/u/Sean_Matthews)\
**Post date:** [January 9, 2020, 1:36pm UTC](https://discourse.julialang.org/t/are-the-entries-in-a-vector-of-immutable-structs-stored-in-place-or-is-there-always-a-pointer-to-the-heap/33141/3 "2020-01-09T13:36:21Z")

</div>

thanks.

---

<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:** [January 9, 2020, 1:37pm UTC](https://discourse.julialang.org/t/are-the-entries-in-a-vector-of-immutable-structs-stored-in-place-or-is-there-always-a-pointer-to-the-heap/33141/4 "2020-01-09T13:37:09Z")

</div>

But only if they are also `isbits`, no?

---

<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 9, 2020, 1:38pm UTC](https://discourse.julialang.org/t/are-the-entries-in-a-vector-of-immutable-structs-stored-in-place-or-is-there-always-a-pointer-to-the-heap/33141/5 "2020-01-09T13:38:22Z")

</div>

> [@mauro3](#):
>
> But only if they are also `isbits` , no?

In 1.4+ it is also for structs containing certain type of uinions:

```julia
julia> struct Foo
           a::Union{Nothing, Float64}
       end

julia> Base.allocatedinline(Foo)
true

```

---

<div class="post-metadata">

**Author:** ![cstjean](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cstjean/32/1444_2.png) [@cstjean](https://discourse.julialang.org/u/cstjean)\
**Post date:** [January 9, 2020, 3:21pm UTC](https://discourse.julialang.org/t/are-the-entries-in-a-vector-of-immutable-structs-stored-in-place-or-is-there-always-a-pointer-to-the-heap/33141/6 "2020-01-09T15:21:57Z")

</div>

Wait. What changed in 1.4? I thought that efficient arrays of small unions was a thing dating from Julia 0.7 (eg. the whole `missing` efficiency thing). Did the storage strategy change?

---

<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 9, 2020, 3:49pm UTC](https://discourse.julialang.org/t/are-the-entries-in-a-vector-of-immutable-structs-stored-in-place-or-is-there-always-a-pointer-to-the-heap/33141/7 "2020-01-09T15:49:12Z")

</div>

> [@cstjean](#):
>
> I thought that efficient arrays of small unions was a thing dating from Julia 0.7 (eg. the whole `missing` efficiency thing). Did the storage strategy change?

Doing the union splitting optimization is orthogonal to how things are stored. And yes, that did change:

> <https://github.com/JuliaLang/julia/pull/32448>
>
> …tored inline in arrays
> 
> This allows more structures to be stored inline in ar…rays, like:
> \`\`\`julia
> struct Foo
> x::Int
> y::Union{Float64, Missing}
> end
> \# also namedtuples
> NamedTuple{(:x, :y), Tuple{Int, Union{Float64, Missing}}}
> \`\`\`
> We already had an \`isinlinealloc\` flag on \`DataType\`, so we switch \`jl\_islayout\_inline\` to use that instead of just \`isbitstype\`. Then, when we're setting the \`isinlinealloc\` flag for a DataType, we just check that each field is \`isbitstype\` or \`isbitsunion\`.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [January 9, 2020, 5:40pm UTC](https://discourse.julialang.org/t/are-the-entries-in-a-vector-of-immutable-structs-stored-in-place-or-is-there-always-a-pointer-to-the-heap/33141/8 "2020-01-09T17:40:49Z")

</div>

> [@mauro3](#):
>
> But only if they are also `isbits` , no?

~~My understanding was that the _struct_ is still stored inline for non-`isbits` types, but the _contents_ of the struct may be pointers.~~ _Update_: this is wrong, see below.

---

<div class="post-metadata">

**Author:** ![cstjean](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cstjean/32/1444_2.png) [@cstjean](https://discourse.julialang.org/u/cstjean)\
**Post date:** [January 9, 2020, 5:56pm UTC](https://discourse.julialang.org/t/are-the-entries-in-a-vector-of-immutable-structs-stored-in-place-or-is-there-always-a-pointer-to-the-heap/33141/9 "2020-01-09T17:56:52Z")

</div>

Ah, right, I got confused. I thought of

```julia
julia> Base.allocatedinline(Union{Nothing, Float64})
true

```

which is true in Julia 1.0-1.3. Thank you for the reference, that is cool.

---

<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 9, 2020, 5:57pm UTC](https://discourse.julialang.org/t/are-the-entries-in-a-vector-of-immutable-structs-stored-in-place-or-is-there-always-a-pointer-to-the-heap/33141/10 "2020-01-09T17:57:41Z")

</div>

> [@stevengj](#):
>
> My understanding is that the _struct_ is still stored inline for non- `isbits` types, but the _contents_ of the struct may be pointers.

I don’t think so because you would then have to recreate the Julia object holding those structs on `getindex`. So either the data is stored inline, or you have pointers to structs.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [January 9, 2020, 6:06pm UTC](https://discourse.julialang.org/t/are-the-entries-in-a-vector-of-immutable-structs-stored-in-place-or-is-there-always-a-pointer-to-the-heap/33141/11 "2020-01-09T18:06:04Z")

</div>

> [@kristoffer.carlsson](#):
>
> So either the data is stored inline, or you have pointers to structs.

You’re right, sorry:

```julia
julia> struct Foo . # struct with non-isbits fields
           x::Any
           y::Any
       end

julia> Foo(3,4)
Foo(3, 4)

julia> a = [Foo(3,4)]
1-element Array{Foo,1}:
 Foo(3, 4)

julia> sizeof(a) / sizeof(Int)
1.0

```

If the fields were stored inline, the size would be 2 pointers (`2*sizeof(Int)`), not 1.
