# Are mutable structs fundamentally slower?

**URL:** <https://discourse.julialang.org/t/are-mutable-structs-fundamentally-slower/5786>\
**Category:** General Usage\
**Tags:** question, type\
**Created:** [September 8, 2017, 3:01pm UTC](https://discourse.julialang.org/t/are-mutable-structs-fundamentally-slower/5786 "2017-09-08T15:01:51Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![sg-s](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sg-s/32/2635_2.png) [@sg-s](https://discourse.julialang.org/u/sg-s)\
**Post date:** [September 8, 2017, 3:01pm UTC](https://discourse.julialang.org/t/are-mutable-structs-fundamentally-slower/5786/1 "2017-09-08T15:01:51Z")

</div>

I’m writing a simulation that solves a system of N differential equations. I’m using fixed step Euler integration, so it’s always a simply for loop that iterates over many times. I have two implementations, and one is 4X faster than the other, and has 30% the allocations. I’d like to understand why:

```julia
# fast code
f1(V::Float64,dt) = some function of V
f2(V::Float64,dt) = some function of V
...
fN(V::Float64,dt) = some function of V

integrate(t::CustomType,dt::Float64)
   var1::Float64
   var2::Float64
   ...
   varN::Float64

   for i = 2:nsteps
       var1 = f1(var1,dt)
       ...
       varN = fN(varN,dt)
   end
end

```

This is rigid code, in the sense that if I want to modify my system by omitting a few variables and corresponding functions, it is laborious to rewrite. Instead, I wrote these structs and associated functions. This is nicer conceptually, but runs much slower:

```julia
# slow code
abstract Type X
end

mutable struct X1 <: X
    v1 
end

function integrate(x::X1,dt::Float64)
   x.v1 = f1(x.v1,dt)
end

mutable struct Wrapper
    all_X::Array{X,1}
end

# now I can define my core integration loop nicely:

function integrate(w::Wrapper,dt)
    for x in w.all_X
         integrate(x,dt)
    end
end

```

I really want to write code like the second case – it’s a lot more flexible, and prevents me from repeating code. But the second implementation is 4 times slower than the first. Any tips on why would be appreciated, as would help on how to get it to run faster.

---

<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:** [September 8, 2017, 3:16pm UTC](https://discourse.julialang.org/t/are-mutable-structs-fundamentally-slower/5786/2 "2017-09-08T15:16:05Z")

</div>

> [@sg-s](#):
>
> mutable struct Wrapper  
> all\_X::Array{X,1}  
> end

This is a mutable struct which doesn’t concretely type its fields. This makes `w.all_X` not type stable, which then makes `integrate(x,dt)` dynamically dispatch. Instead, use a type parameter

```julia
mutable struct Wrapper{T<:X}
    all_X::Array{T,1}
end

```

and it’ll be much better.

Another thing to mention is that the way you are writing the functions you are assuming the differential equations are all independent. This is not true in general nor is it true in most cases (though it may be for your case, I don’t know), so you should be cautious about this approach unless it’s for a very specific purpose.

---

<div class="post-metadata">

**Author:** ![sg-s](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sg-s/32/2635_2.png) [@sg-s](https://discourse.julialang.org/u/sg-s)\
**Post date:** [September 8, 2017, 3:28pm UTC](https://discourse.julialang.org/t/are-mutable-structs-fundamentally-slower/5786/3 "2017-09-08T15:28:08Z")

</div>

Hi Chris,

Thanks!

I need some further help: My mutable struct is actually a little more complicated:

```julia
mutable struct Wrapper
    a::Float64
    b::Float64  
    c::Float64
    all_X::Array{X,1}

   # inner constructor 
   Wrapper() = new(0.,0.,0.,Array{X,1}())
end

```

How do I modify this to match what you suggested?

---

<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:** [September 8, 2017, 3:35pm UTC](https://discourse.julialang.org/t/are-mutable-structs-fundamentally-slower/5786/4 "2017-09-08T15:35:38Z")

</div>

> [@sg-s](#):
>
> mutable struct Wrapper  
> a::Float64  
> b::Float64  
> c::Float64  
> all\_X::Array{X,1}
> 
> # inner constructor
> 
> Wrapper() = new(0.,0.,0.,Array{X,1}())  
> end

```julia
mutable struct Wrapper{T}
    a::Float64
    b::Float64  
    c::Float64
    all_X::Array{T,1}

   # inner constructor 
   Wrapper{T}() = new(0.,0.,0.,Array{T,1}())
end

```

This would need you to pass in the type for the array into the inner constructor though, so you might want to have a default one as well.

---

<div class="post-metadata">

**Author:** ![sg-s](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sg-s/32/2635_2.png) [@sg-s](https://discourse.julialang.org/u/sg-s)\
**Post date:** [September 8, 2017, 3:41pm UTC](https://discourse.julialang.org/t/are-mutable-structs-fundamentally-slower/5786/5 "2017-09-08T15:41:10Z")

</div>

thanks – two further questions if you don’t mind:

1. I don’t see the abstract type ‘X’ references anywhere here. Should it be

```julia
mutable struct Wrapper{T<:X}

```

1. How do I create a new object of this type? I tried

```julia
w = Wrapper()
ERROR: MethodError: no method matching Wrapper()

w = Wrapper({X})
ERROR: syntax: { } vector syntax is discontinued

w = Wrapper{X}()
ERROR: MethodError: no method matching Wrapper{X}()

```

thanks a ton!

* * *

**update**

I managed to get this working, but without an inner constructor (I used an external constructor)

Sadly, there’s no change in the speed of the code.

---

<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:** [September 8, 2017, 5:23pm UTC](https://discourse.julialang.org/t/are-mutable-structs-fundamentally-slower/5786/6 "2017-09-08T17:23:51Z")

</div>

> [@sg-s](#):
>
> Sadly, there’s no change in the speed of the code.

Can you show what you have now? Are you sure everything is strictly typed and inferred? And for mutable structs, did you make sure you’re only mutating them and not creating them a bunch? (If you want to create them a bunch, just use a `struct`)

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [September 8, 2017, 5:35pm UTC](https://discourse.julialang.org/t/are-mutable-structs-fundamentally-slower/5786/7 "2017-09-08T17:35:05Z")

</div>

FYI v1 field is still not typed afaict

---

<div class="post-metadata">

**Author:** ![sg-s](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sg-s/32/2635_2.png) [@sg-s](https://discourse.julialang.org/u/sg-s)\
**Post date:** [September 8, 2017, 6:41pm UTC](https://discourse.julialang.org/t/are-mutable-structs-fundamentally-slower/5786/8 "2017-09-08T18:41:31Z")

</div>

Hi Chris,

Here’s a zip file that has two implementations of my simulations, one with mutable structs and one without. The one without runs 5X faster than the one with.

[https://www.dropbox.com/s/r5u318q7qo5b0yk/slow\_fast.zip?dl=0](https://www.dropbox.com/s/r5u318q7qo5b0yk/slow_fast.zip?dl=0)

---

<div class="post-metadata">

**Author:** ![sg-s](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sg-s/32/2635_2.png) [@sg-s](https://discourse.julialang.org/u/sg-s)\
**Post date:** [September 8, 2017, 6:44pm UTC](https://discourse.julialang.org/t/are-mutable-structs-fundamentally-slower/5786/9 "2017-09-08T18:44:00Z")

</div>

Hi yuyichao,

yes, in this example it isn’t. This is my actual code:

```julia
mutable struct NaV <: Conductance
    g::Float64
    m::Float64
    h::Float64
    E::Float64

    # constructor
    NaV(x::Float64) = new(x,0.,0.,30.)
end

```

so this should be typed, right? I ran `@code_warntype` and got nothing in red
