# Why mutable structs are allocated on the heap?

**URL:** https://discourse.julialang.org/t/why-mutable-structs-are-allocated-on-the-heap/12992
**Category:** General Usage
**Tags:** question
**Created:** [August 7, 2018, 2:02pm UTC](https://discourse.julialang.org/t/why-mutable-structs-are-allocated-on-the-heap/12992 "2018-08-07T14:02:04Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![e3c6](https://avatars.discourse-cdn.com/v4/letter/e/e79b87/32.png) [@e3c6](https://discourse.julialang.org/u/e3c6)
#### Post date: [August 7, 2018, 2:02pm UTC](https://discourse.julialang.org/t/why-mutable-structs-are-allocated-on-the-heap/12992/1 "2018-08-07T14:02:04Z")

</div>

From [https://docs.julialang.org/en/latest/manual/types/#Mutable-Composite-Types-1:](https://docs.julialang.org/en/latest/manual/types/#Mutable-Composite-Types-1:)

> In order to support mutation, such objects are generally allocated on the heap, and have stable memory addresses.

If I define:

```julia
mutable struct MyT
x::Int
end 

```

and then use `MyT` inside a function, such as:

```julia
function f(x::Int) 
q = MyT(x);
q.x += 1
return q.x
end

```

I would expect `q` to be allocated on the stack, because it is a local variable that does not change type and `MyT` is `isbits`. But it is not:

`@btime f(1) # 3.781 ns (1 allocation: 16 bytes)`

Why?

---

<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: [August 7, 2018, 2:06pm UTC](https://discourse.julialang.org/t/why-mutable-structs-are-allocated-on-the-heap/12992/2 "2018-08-07T14:06:18Z")

</div>

Julia has many optimisations, eliminating unnecessary allocations is one of them.

---

<div class="post-metadata">

### Author: ![e3c6](https://avatars.discourse-cdn.com/v4/letter/e/e79b87/32.png) [@e3c6](https://discourse.julialang.org/u/e3c6)
#### Post date: [August 7, 2018, 2:12pm UTC](https://discourse.julialang.org/t/why-mutable-structs-are-allocated-on-the-heap/12992/3 "2018-08-07T14:12:16Z")

</div>

But in this case the allocation seems unnecessary, yet it occurs. Or am I missing something?

---

<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: [August 7, 2018, 2:13pm UTC](https://discourse.julialang.org/t/why-mutable-structs-are-allocated-on-the-heap/12992/4 "2018-08-07T14:13:57Z")

</div>

Sorry, on 0.7 this optimization is much more effective:

```julia
julia> @btime f(1)
  1.503 ns (0 allocations: 0 bytes)
2

julia> VERSION
v"0.7.0-rc3.3"

```

---

<div class="post-metadata">

### Author: ![e3c6](https://avatars.discourse-cdn.com/v4/letter/e/e79b87/32.png) [@e3c6](https://discourse.julialang.org/u/e3c6)
#### Post date: [August 7, 2018, 2:15pm UTC](https://discourse.julialang.org/t/why-mutable-structs-are-allocated-on-the-heap/12992/5 "2018-08-07T14:15:11Z")

</div>

Is there an easy to state rule to know when something will be allocated on the heap vs. the stack? If not, is there a macro (something like `@code_warntype`) that alerts me when a variable is heap allocated?

---

<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: [August 7, 2018, 2:16pm UTC](https://discourse.julialang.org/t/why-mutable-structs-are-allocated-on-the-heap/12992/6 "2018-08-07T14:16:50Z")

</div>

0.6:

```julia
julia> @code_typed f(1)
CodeInfo(:(begin
        q = $(Expr(:new, :(Main.MyT), :(x))) # line 3:
        SSAValue(0) = (Base.add_int)((Core.getfield)(q, :x)::Int64, 1)::Int64
        (Core.setfield!)(q, :x, SSAValue(0))::Int64 # line 4:
        return (Core.getfield)(q, :x)::Int64
    end))=>Int64

```

0.7

```julia
julia> @code_typed f(1)
CodeInfo(
3 1 ─ %1 = (Base.add_int)(x, 1)::Int64 │╻ +
  └── goto #3 if not false │
  2 ─ nothing::Nothing │
4 3 ─ return %1 │
) => Int64

```

Can see that the `new` call creating the mutable type is elided.

---

<div class="post-metadata">

### Author: ![e3c6](https://avatars.discourse-cdn.com/v4/letter/e/e79b87/32.png) [@e3c6](https://discourse.julialang.org/u/e3c6)
#### Post date: [August 7, 2018, 2:19pm UTC](https://discourse.julialang.org/t/why-mutable-structs-are-allocated-on-the-heap/12992/7 "2018-08-07T14:19:17Z")

</div>

Thanks.

---

<div class="post-metadata">

### Author: ![e3c6](https://avatars.discourse-cdn.com/v4/letter/e/e79b87/32.png) [@e3c6](https://discourse.julialang.org/u/e3c6)
#### Post date: [August 7, 2018, 3:30pm UTC](https://discourse.julialang.org/t/why-mutable-structs-are-allocated-on-the-heap/12992/8 "2018-08-07T15:30:46Z")

</div>

One more question. If I have a vector of `mutable structs` such as this one (which only contain isbits fields), the vector will be a pointer to a list of pointers to the structs, or a single pointer to a single chunk of memory with all the structs?

---

<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: [August 7, 2018, 3:33pm UTC](https://discourse.julialang.org/t/why-mutable-structs-are-allocated-on-the-heap/12992/9 "2018-08-07T15:33:25Z")

</div>

They will not lie contiguously in memory.

---

<div class="post-metadata">

### Author: ![e3c6](https://avatars.discourse-cdn.com/v4/letter/e/e79b87/32.png) [@e3c6](https://discourse.julialang.org/u/e3c6)
#### Post date: [August 7, 2018, 3:36pm UTC](https://discourse.julialang.org/t/why-mutable-structs-are-allocated-on-the-heap/12992/10 "2018-08-07T15:36:46Z")

</div>

Is there a way to force a contiguous block? Like for instance perhaps casting the Vector to a Tuple might be a good idea in this case?

---

<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: [August 7, 2018, 3:58pm UTC](https://discourse.julialang.org/t/why-mutable-structs-are-allocated-on-the-heap/12992/11 "2018-08-07T15:58:12Z")

</div>

> [@e3c6](#):
>
> Is there a way to force a contiguous block?

Don’t use `mutable`

---

<div class="post-metadata">

### Author: ![Stephen\_Vavasis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stephen_vavasis/32/3389_2.png) [@Stephen\_Vavasis](https://discourse.julialang.org/u/Stephen_Vavasis)
#### Post date: [August 8, 2018, 2:19pm UTC](https://discourse.julialang.org/t/why-mutable-structs-are-allocated-on-the-heap/12992/12 "2018-08-08T14:19:29Z")

</div>

Just to elaborate on this a bit: if you want a contiguous array of structs, then they need to be immutable. But suppose you want to change a field in one of those structs? The Julian way to do it is to copy the whole struct over and then count on compiler optimizations to elide needless work. For example, here is a function (not tested) that changes one field of a struct that lives inside of an array:

```julia
    struct A
        a::Int
        b::Bool
    end

    function changeb!(v::Vector{A}, ind, newb::Bool)
        v[ind] = A(v[ind].a, newb)
        nothing
    end

```

For a struct that has many fields, this can get awkward. I wrote a macro a long time ago to automatically generate the above kind of code, but I haven’t used it recently, and I’m not sure it works any more. I suspect someone else may have a package for this purpose.

---

<div class="post-metadata">

### Author: ![tk3369](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tk3369/32/2824_2.png) [@tk3369](https://discourse.julialang.org/u/tk3369)
#### Post date: [August 8, 2018, 2:57pm UTC](https://discourse.julialang.org/t/why-mutable-structs-are-allocated-on-the-heap/12992/13 "2018-08-08T14:57:49Z")

</div>

Can they lie contiguously in memory when all attributes of the mutable struct are fixed length eg bits type?

---

<div class="post-metadata">

### Author: ![Gnimuc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gnimuc/32/2194_2.png) [@Gnimuc](https://discourse.julialang.org/u/Gnimuc)
#### Post date: [August 8, 2018, 3:27pm UTC](https://discourse.julialang.org/t/why-mutable-structs-are-allocated-on-the-heap/12992/14 "2018-08-08T15:27:30Z")

</div>

[https://github.com/simonster/StructsOfArrays.jl](https://github.com/simonster/StructsOfArrays.jl)

A little bit off-topic: this might be useful if you want every field in the immutable struct stored contiguously in memory.

---

<div class="post-metadata">

### Author: ![Stephen\_Vavasis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stephen_vavasis/32/3389_2.png) [@Stephen\_Vavasis](https://discourse.julialang.org/u/Stephen_Vavasis)
#### Post date: [August 8, 2018, 3:32pm UTC](https://discourse.julialang.org/t/why-mutable-structs-are-allocated-on-the-heap/12992/15 "2018-08-08T15:32:14Z")

</div>

The issue of mutable/immutable structs is orthogonal to the issue of whether its fields are bits/nonbits. In other words, a particular mutable struct may have only bits objects, but it is still mutable (one can change the fields individually). Similarly, an immutable struct may have nonbits entries, but it is still immutable (one cannot change the fields individually). In terms of the memory layout, for both mutable and immutable, a nonbits field is stored via a pointer inside the struct, whereas a bits field is stored directly. (Note: the compiler is allowed to emit code that implements these properties differently for the purpose of improving performance as long as the results are indistinguishable from this description.)

For an array of structs, as Kristoffer Carlsson said, there is contiguous memory layout only for immutable structs. And if those immutable structs contain nonbits fields, then each struct object in the array internally will have pointers, so the data in the array may still be scattered.

---

<div class="post-metadata">

### Author: ![e3c6](https://avatars.discourse-cdn.com/v4/letter/e/e79b87/32.png) [@e3c6](https://discourse.julialang.org/u/e3c6)
#### Post date: [August 9, 2018, 4:21pm UTC](https://discourse.julialang.org/t/why-mutable-structs-are-allocated-on-the-heap/12992/16 "2018-08-09T16:21:49Z")

</div>

Note that Julia `isbits` returns false for a mutable struct, even if all the fields are `isbits`. I agree with the distinction of mutable/immutable vs. bits/nonbits… but then why `isbits` behaves like this?

---

<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: [August 9, 2018, 4:25pm UTC](https://discourse.julialang.org/t/why-mutable-structs-are-allocated-on-the-heap/12992/17 "2018-08-09T16:25:46Z")

</div>

> [@e3c6](#):
>
> but then why `isbits` behaves like this

This explains it quite well I think:

```julia
help?> isbits
search: isbits isbitstype disable_sigint

  isbits(x)

  Return true if x is an instance of an isbitstype type.

help?> isbitstype
search: isbitstype

  isbitstype(T)

  Return true if type T is a "plain data" type, meaning it is immutable and contains no references to other values,
  only primitive types and other isbitstype types. Typical examples are numeric types such as UInt8, Float64, and
  Complex{Float64}. This category of types is significant since they are valid as type parameters, may not track
  isdefined / isassigned status, and have a defined layout that is compatible with C.

  Examples
  ≡≡≡≡≡≡≡≡≡≡

  julia> isbitstype(Complex{Float64})
  true

  julia> isbitstype(Complex)
  false

```

---

<div class="post-metadata">

### Author: ![Raf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raf/32/3383_2.png) [@Raf](https://discourse.julialang.org/u/Raf)
#### Post date: [August 9, 2018, 4:32pm UTC](https://discourse.julialang.org/t/why-mutable-structs-are-allocated-on-the-heap/12992/18 "2018-08-09T16:32:26Z")

</div>

[Setfeild.jl](https://github.com/jw3126/Setfield.jl) does this.

---

<div class="post-metadata">

### Author: ![e3c6](https://avatars.discourse-cdn.com/v4/letter/e/e79b87/32.png) [@e3c6](https://discourse.julialang.org/u/e3c6)
#### Post date: [August 22, 2018, 12:39pm UTC](https://discourse.julialang.org/t/why-mutable-structs-are-allocated-on-the-heap/12992/19 "2018-08-22T12:39:35Z")

</div>

I’m still a bit confused about why mutable structs, even if all its fields are `isbits`, might require heap allocation. If a variable is defined in a function scope, and not returned, it can be safely deleted after the function scope exits. Then what’s wrong with stack allocating it (whether it is of mutable or immutable type, but with all fields of `isbits` type so it has a compile-time defined size), as long as its inside a function? Is there a simple example where this does not work?

---

<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: [August 22, 2018, 12:43pm UTC](https://discourse.julialang.org/t/why-mutable-structs-are-allocated-on-the-heap/12992/20 "2018-08-22T12:43:03Z")

</div>

> [@e3c6](#):
>
> If a variable is defined in a function scope, and not returned, it can be safely deleted after the function scope exits.

Eliding allocations when a non isbits struct is created and known not to escape is an optimization that is already happening.

But the discussion above was about how they will be stored in an Array?

[Next page](https://discourse.julialang.org/t/why-mutable-structs-are-allocated-on-the-heap/12992.md?page=2)
