# Optimising function with const instead of struct?

**URL:** https://discourse.julialang.org/t/optimising-function-with-const-instead-of-struct/12233
**Category:** Performance
**Created:** [July 7, 2018, 6:46am UTC](https://discourse.julialang.org/t/optimising-function-with-const-instead-of-struct/12233 "2018-07-07T06:46:24Z")
**Posts on this page:** 10
**Page:** 1

<div class="post-metadata">

### Author: ![rveltz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rveltz/32/2707_2.png) [@rveltz](https://discourse.julialang.org/u/rveltz)
#### Post date: [July 7, 2018, 6:46am UTC](https://discourse.julialang.org/t/optimising-function-with-const-instead-of-struct/12233/1 "2018-07-07T06:46:24Z")

</div>

Hi,

I have a function that I used for modelling purposes (kinda using an ODE). Hence, I defined a `mutable struct` to encapsulate all parameters. I thought the compiler would optimised out the values of the const inside the function but it seems it doesnot. Is there a way to improve to performance of the following code `f(p1)` ?

I think this is related to [this](https://discourse.julialang.org/t/const-static-function-parameters/1803/17) as well.

```julia
using BenchmarkTools

mutable struct Type1
       t_end::Float64         
end

struct Type2
       t_end::Float64         
end

p1 = Type1(100)
p2 = Type2(100)
const p3 = 100.

function f(p)
	return 2*p.t_end
end
	
function f_const()
	return 2*p3
end

@btime f(p1)
@btime f(p2)
@btime f_const()

```

results are

```julia
julia> @btime f(p1)
  33.832 ns (2 allocations: 32 bytes)
200.0

julia> @btime f(p2)
  34.211 ns (2 allocations: 32 bytes)
200.0

julia> @btime f_const()
  1.706 ns (0 allocations: 0 bytes)
200.0

```

```julia

```

---

<div class="post-metadata">

### Author: ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)
#### Post date: [July 7, 2018, 6:55am UTC](https://discourse.julialang.org/t/optimising-function-with-const-instead-of-struct/12233/2 "2018-07-07T06:55:57Z")

</div>

You need to interpolate your arguments into the benchmark expression: [GitHub - JuliaCI/BenchmarkTools.jl: A benchmarking framework for the Julia language](https://github.com/JuliaCI/BenchmarkTools.jl#quick-start) otherwise the difference between the two results is just showing the overhead of accessing a non-constant global variable. Doing so makes all the results perform identically:

```julia
julia> @btime f_const()
  1.754 ns (0 allocations: 0 bytes)
200.0

julia> @btime f($p1)
  1.754 ns (0 allocations: 0 bytes)
200.0

```

Can you clarify what constant optimizations you’re expecting to see?

---

<div class="post-metadata">

### Author: ![rveltz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rveltz/32/2707_2.png) [@rveltz](https://discourse.julialang.org/u/rveltz)
#### Post date: [July 7, 2018, 7:14am UTC](https://discourse.julialang.org/t/optimising-function-with-const-instead-of-struct/12233/3 "2018-07-07T07:14:48Z")

</div>

Thank you! What I meant is that the function actuallty looks like `f(x,p)` where `p` does not change during the calls. Maybe wrapping like `f_wrap = -> f(x,p)` would do the trick. I will try.

---

<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: [July 7, 2018, 8:29am UTC](https://discourse.julialang.org/t/optimising-function-with-const-instead-of-struct/12233/4 "2018-07-07T08:29:11Z")

</div>

The const one isn’t doing anything. It realizes that there’s a constant solution of 200.0 and compiles a function that just spits that out instead of doing a computation (when `const` is declared, it doesn’t just assume constant type but also constant value). That can’t be done with the others since they aren’t declared constant.

---

<div class="post-metadata">

### Author: ![jlapeyre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jlapeyre/32/4514_2.png) [@jlapeyre](https://discourse.julialang.org/u/jlapeyre)
#### Post date: [July 7, 2018, 8:51am UTC](https://discourse.julialang.org/t/optimising-function-with-const-instead-of-struct/12233/5 "2018-07-07T08:51:45Z")

</div>

I think there is one typo. Then two nonconstant globals.  
Maybe this is what you want?

```julia
using BenchmarkTools

mutable struct Type1
       t_end::Float64         
end

struct Type2
       t_end::Float64         
end

const p1 = Type1(100)
const p2 = Type2(100)
const p3 = 100.

function f(p)
	return 2*p.t_end
end
	
function f_const()
	return 2*p3
end

@btime f(p1)
@btime f(p2)
@btime f_const()

```

Results are

```julia
  1.831 ns (0 allocations: 0 bytes)
  0.014 ns (0 allocations: 0 bytes)
  0.014 ns (0 allocations: 0 bytes)

```

---

<div class="post-metadata">

### Author: ![rveltz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rveltz/32/2707_2.png) [@rveltz](https://discourse.julialang.org/u/rveltz)
#### Post date: [July 7, 2018, 9:35am UTC](https://discourse.julialang.org/t/optimising-function-with-const-instead-of-struct/12233/7 "2018-07-07T09:35:37Z")

</div>

Your code gives the same results my machine (v0.6.3)

```julia
julia> @btime f(p1)
  1.506 ns (0 allocations: 0 bytes)
200.0

julia> @btime f(p2)
  1.551 ns (0 allocations: 0 bytes)
200.0

julia> @btime f_const()
  1.312 ns (0 allocations: 0 bytes)
200.0

```

---

<div class="post-metadata">

### Author: ![rveltz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rveltz/32/2707_2.png) [@rveltz](https://discourse.julialang.org/u/rveltz)
#### Post date: [July 7, 2018, 9:37am UTC](https://discourse.julialang.org/t/optimising-function-with-const-instead-of-struct/12233/8 "2018-07-07T09:37:46Z")

</div>

There is a typo, so I repost the results:

```julia
using BenchmarkTools

mutable struct Type1
       t_end::Float64         
end

struct Type2
       t_end::Float64         
end

p1 = Type1(100)
p2 = Type2(100)
const p3 = 100.

function f(p)
	return 2*p.t_end
end
	
function f_const()
	return 2*p3
end

@btime f($p1)
@btime f($p2)
@btime f_const()

```

I get

```julia
julia> @btime f($p1)
  1.313 ns (0 allocations: 0 bytes)
200.0

julia> @btime f($p2)
  1.248 ns (0 allocations: 0 bytes)
200.0

julia> @btime f_const()
  1.488 ns (0 allocations: 0 bytes)
200.0

```

---

<div class="post-metadata">

### Author: ![jlapeyre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jlapeyre/32/4514_2.png) [@jlapeyre](https://discourse.julialang.org/u/jlapeyre)
#### Post date: [July 7, 2018, 9:48am UTC](https://discourse.julialang.org/t/optimising-function-with-const-instead-of-struct/12233/9 "2018-07-07T09:48:57Z")

</div>

My results on v0.6.3 agree with yours.  
I am surprised that `f(p2)` and especially `f_const()` are not optimized as they are for v0.7

With this

```julia
function f_const2()
    return 200.0
end

```

`@btime f_const2()` returns

```julia
  0.014 ns (0 allocations: 0 bytes)

```

on both v0.6.3 and v0.7, as expected.  
[EDIT: commented on `f_const()`]

---

<div class="post-metadata">

### Author: ![jlapeyre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jlapeyre/32/4514_2.png) [@jlapeyre](https://discourse.julialang.org/u/jlapeyre)
#### Post date: [July 7, 2018, 10:13am UTC](https://discourse.julialang.org/t/optimising-function-with-const-instead-of-struct/12233/10 "2018-07-07T10:13:42Z")

</div>

I guess I shouldn’t be surprised. But, I thought that compiler optimization had been implemented earlier. For this

```julia
const x = 1
f() = x

```

I get the same non-optimized result for v0.5 and v0.6.x. But, it is optimized for v0.7.

---

<div class="post-metadata">

### Author: ![Elrod](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/elrod/32/22461_2.png) [@Elrod](https://discourse.julialang.org/u/Elrod)
#### Post date: [July 7, 2018, 10:44am UTC](https://discourse.julialang.org/t/optimising-function-with-const-instead-of-struct/12233/11 "2018-07-07T10:44:12Z")

</div>

> [@jlapeyre](#):
>
> function f\_const() return 2\*p3 end

I tried on two computers, with builds of master dating 7/5 and 7/6.  
The older one gives me:

```julia
julia> @code_warntype f_const()
Body::Float64
2 1 ─ return 200.0

```

while both give

```julia
julia> @code_llvm f_const()

; Function f_const
; Location: REPL[4]:2
define double @julia_f_const_32945() {
top:
  ret double 2.000000e+02
}

```

but only the older one has:

```julia
julia> @btime f_const()
  0.030 ns (0 allocations: 0 bytes)
200.0

```

The other is a little over 1ns. It seems like it ought to be unnecessary, but `@generated f_const() = 2p3` works as expected.

EDIT:  
I rebuilt Julia master on the computer that computer, and now I’m getting the same \>1ns runtime, with `@code_typed` saying

```julia
2 1 ─ %1 = Base.mul_float(2.0, 100.0)::Float64 │╻╷ *
  └── return %1

```

So, there seems to have been a change between

```julia
Version 0.7.0-beta.157 (2018-07-05 00:54 UTC)
master/aba7068* (fork: 5 commits, 2 days)

```

and

```julia
Version 0.7.0-beta.188 (2018-07-06 20:54 UTC)
Commit a60119b57f (1 days old master)

```

(the fork and commits should be totally unrelated)
