# Improving performance due to setting types of the fields of a struct

**URL:** <https://discourse.julialang.org/t/improving-performance-due-to-setting-types-of-the-fields-of-a-struct/24965>\
**Category:** Performance\
**Created:** [June 5, 2019, 2:45pm UTC](https://discourse.julialang.org/t/improving-performance-due-to-setting-types-of-the-fields-of-a-struct/24965 "2019-06-05T14:45:54Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![Volker](https://avatars.discourse-cdn.com/v4/letter/v/77aa72/32.png) [@Volker](https://discourse.julialang.org/u/Volker)\
**Post date:** [June 5, 2019, 2:45pm UTC](https://discourse.julialang.org/t/improving-performance-due-to-setting-types-of-the-fields-of-a-struct/24965/1 "2019-06-05T14:45:54Z")

</div>

Hi,

I have a question about improving the performance of Julia. In the Julia documentation is something explained about setting types of a structs.

"  
You can do better by declaring the type of `a` . Here, we are focused on the case where `a` might be any one of several types, in which case the natural solution is to use parameters. For example:

```julia
julia> mutable struct MyType{T<:AbstractFloat}
           a::T
       end

```

This is a better choice than

```julia
julia> mutable struct MyStillAmbiguousType
           a::AbstractFloat
       end

```

because the first version specifies the type of `a` from the type of the wrapper object.  
"

My question is now: Is is also better, if you have multiple fields of the struct  
In example:

```julia
julia> mutable struct MyType{T<:Float64, I<:Int64}
           a::T 
           b::T
           c::I
           d::I
       end

```

```julia
julia> mutable struct MyStillAmbiguousType
           a::Float64
           b::Float64
           c::Int64
           d::Int64
       end

```

---

<div class="post-metadata">

**Author:** ![JeffreySarnoff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeffreysarnoff/32/1980_2.png) [@JeffreySarnoff](https://discourse.julialang.org/u/JeffreySarnoff)\
**Post date:** [June 5, 2019, 2:59pm UTC](https://discourse.julialang.org/t/improving-performance-due-to-setting-types-of-the-fields-of-a-struct/24965/2 "2019-06-05T14:59:33Z")

</div>

yes,no,maybe. You are doing the same thing two different ways.

```julia
[mutable] struct Test{F<:AbstractFloat, I<:Integer}
    afloat::F
    anint::I
    anotherint::I 
end

```

does more for you.

The next thing to consider is “does this struct need to be mutable?”  
If you usually keep the initial values, your performance will likely increase by using `struct` rather than `mutable struct`. On the occasions where you change a value, just create a new struct – if that is appropriate to your data flow.

---

<div class="post-metadata">

**Author:** ![tim.holy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tim.holy/32/52_2.png) [@tim.holy](https://discourse.julialang.org/u/tim.holy)\
**Post date:** [June 5, 2019, 3:15pm UTC](https://discourse.julialang.org/t/improving-performance-due-to-setting-types-of-the-fields-of-a-struct/24965/3 "2019-06-05T15:15:23Z")

</div>

From your question, I worry you’re missing the point of that section: the problem is with the `AbstractFloat`, which as an abstract type has a potentially-limitless set of subtypes. For type declarations of the form `MyStillAmbiguousType` (the version in the docs, not the one you asked about) there is no way to know the type of `obj.a` given that you have an object `obj` of type `MyStillAmbiguousType`. Conversely, `MyType{Float32}` makes it plain that `obj.a` will be a `Float32`. Finally, `MyType{AbstractFloat}` will behave identically to `MyStillAmbiguousType`; the difference is the _possibility_ of using a concrete type as the type parameter.

The two types you asked about are identical: the only subtype of `Float64` is `Float64`, and the only subtype of `Int64` is `Int64`, so there’s really nothing parametric about the first one and nothing ambiguous about the second.

---

<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:** [June 5, 2019, 6:07pm UTC](https://discourse.julialang.org/t/improving-performance-due-to-setting-types-of-the-fields-of-a-struct/24965/4 "2019-06-05T18:07:07Z")

</div>

The difference between these two types is a bit subtle:

```julia
mutable struct Param{T<:Integer}
    field::T
end

mutable struct NoParam
    field::Integer
end

```

I fear that it may have been lost along the way in edits to the manual over time. To clarify:

- the value of `.field` of instances of both `Param` and `NoParam` can be changed, but
- the type of `.field` of an instance of `Param` cannot be changed, whereas
- the type of `.field` of an instance of `NoParam` can be changed.

In other words:

```julia
julia> p = Param(123)
Param{Int64}(123)

julia> n = NoParam(123)
NoParam(123)

julia> p.field = big(2)^1000
ERROR: InexactError: Int64(10715086071862673209484250490600018105614048117055336074437503883703510511249361224931983788156958581275946729175531468251871452856923140435984577574698574803934567774824230985421074605062371141877954182153046474983581941267398767559165543946077062914571196477686542167660429831652624386837205668069376)
Stacktrace:
 [1] Type at ./gmp.jl:354 [inlined]
 [2] convert at ./number.jl:7 [inlined]
 [3] setproperty!(::Param{Int64}, ::Symbol, ::BigInt) at ./Base.jl:21
 [4] top-level scope at REPL[5]:1

julia> n.field = big(2)^1000
10715086071862673209484250490600018105614048117055336074437503883703510511249361224931983788156958581275946729175531468251871452856923140435984577574698574803934567774824230985421074605062371141877954182153046474983581941267398767559165543946077062914571196477686542167660429831652624386837205668069376

```

Moreover, the type of `.field` for a `Param` object is reflected in the type of the `Param` object, so when the compiler generates code for a specific kind of `Param` object, it can specialize on the type of `.field` as well. On the other hand, the type of `.field` of `NoParam` is not captured by the type of the `NoParam` instance and so the generated code is not specialized and has to be general enough to handle any kind of `Integer` that it might encounter there.

---

<div class="post-metadata">

**Author:** ![dilumaluthge](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dilumaluthge/32/29283_2.png) [@dilumaluthge](https://discourse.julialang.org/u/dilumaluthge)\
**Post date:** [June 7, 2019, 4:11am UTC](https://discourse.julialang.org/t/improving-performance-due-to-setting-types-of-the-fields-of-a-struct/24965/5 "2019-06-07T04:11:32Z")

</div>

Perhaps we could add this example to the docs?

---

<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:** [June 7, 2019, 4:25am UTC](https://discourse.julialang.org/t/improving-performance-due-to-setting-types-of-the-fields-of-a-struct/24965/6 "2019-06-07T04:25:58Z")

</div>

I think I did once. Feel free to copy it back in 🙂

---

<div class="post-metadata">

**Author:** ![Volker](https://avatars.discourse-cdn.com/v4/letter/v/77aa72/32.png) [@Volker](https://discourse.julialang.org/u/Volker)\
**Post date:** [July 12, 2019, 6:36am UTC](https://discourse.julialang.org/t/improving-performance-due-to-setting-types-of-the-fields-of-a-struct/24965/7 "2019-07-12T06:36:15Z")

</div>

Hi,

can somebody explain me what I did wrong in this code. It seems that I didn´t know the right syntax for multiple variables

```julia
struct AlgorithmOpt{F<:Float64, S<:String, I<:Int64, B<:Bool}
    sorting::S
    selection::S
    replacement::S
    crossover::S
    mutation::S
    num_size::I
    max_generations::I
    verbose::B
end

```

Because I get the following MethodError

ERROR: LoadError: MethodError: no method matching EaOpt.AlgorithmOpt(::String, ::String, ::String, ::String, ::String, ::Int64, ::Int64, ::Bool)

---

<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:** [July 12, 2019, 6:48am UTC](https://discourse.julialang.org/t/improving-performance-due-to-setting-types-of-the-fields-of-a-struct/24965/8 "2019-07-12T06:48:23Z")

</div>

You have the `F` there which cannot be determined based on the arguments.

However, I would really advice not to include parameters when they can only take a concrete type. Just put the type directly after the field instead.

---

<div class="post-metadata">

**Author:** ![Volker](https://avatars.discourse-cdn.com/v4/letter/v/77aa72/32.png) [@Volker](https://discourse.julialang.org/u/Volker)\
**Post date:** [July 12, 2019, 6:54am UTC](https://discourse.julialang.org/t/improving-performance-due-to-setting-types-of-the-fields-of-a-struct/24965/9 "2019-07-12T06:54:37Z")

</div>

Ok thanks. Then I misunderstood the statemant of StefanKarpinski that it would help the compiler and lead to faster code.

> [@StefanKarpinski](#):
>
> Moreover, the type of `.field` for a `Param` object is reflected in the type of the `Param` object, so when the compiler generates code for a specific kind of `Param` object, it can specialize on the type of `.field` as well. On the other hand, the type of `.field` of `NoParam` is not captured by the type of the `NoParam` instance and so the generated code is not specialized and has to be general enough to handle any kind of `Integer` that it might encounter there.

---

<div class="post-metadata">

**Author:** ![Karajan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/karajan/32/8545_2.png) [@Karajan](https://discourse.julialang.org/u/Karajan)\
**Post date:** [July 12, 2019, 7:26am UTC](https://discourse.julialang.org/t/improving-performance-due-to-setting-types-of-the-fields-of-a-struct/24965/10 "2019-07-12T07:26:46Z")

</div>

The distinction here is whether you have a concrete type (such as `Int64`) or a more general type (such as `Integer` which could be a `Int64` or `Int16` or …).

@StefanKarpinski said above, if you have an `Integer` the compiler can generate faster code if you use parameters, because the `field` of a `Param{Int64}` can only ever be an `Int64`. The `field` of a `NoParam` can change between the different concrete types of `Integer`, so it’s harder to generate specialized code because the compiler can’t know what sort of `Integer` to expect.

However, if you only ever want to use one type of `Integer` (e.g. `Int64`, as in your code) @kristoffer.carlsson advice applies: use

```julia
struct A
    field::Int64
end

```

instead of

```julia
struct A{I <: Int64}
   field::I
end

```

In this case it makes no difference for the compiler because in both cases `field` can only ever be `Int64`.

That said, in many cases you don’t really care what type of `Integer` is used and in that cases it would be beneficial to use parameters and a more liberal type to give the users the choice what kind of `Integer`s they would like to use.

---

<div class="post-metadata">

**Author:** ![Volker](https://avatars.discourse-cdn.com/v4/letter/v/77aa72/32.png) [@Volker](https://discourse.julialang.org/u/Volker)\
**Post date:** [July 12, 2019, 8:03am UTC](https://discourse.julialang.org/t/improving-performance-due-to-setting-types-of-the-fields-of-a-struct/24965/11 "2019-07-12T08:03:49Z")

</div>

Thanks for the explanation. Now I got it
