# Invokelatest() makes code run slower

**URL:** <https://discourse.julialang.org/t/invokelatest-makes-code-run-slower/6027>\
**Category:** Internals & Design\
**Created:** [September 21, 2017, 3:44pm UTC](https://discourse.julialang.org/t/invokelatest-makes-code-run-slower/6027 "2017-09-21T15:44:58Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![chakravala](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chakravala/32/6832_2.png) [@chakravala](https://discourse.julialang.org/u/chakravala)\
**Post date:** [September 21, 2017, 3:44pm UTC](https://discourse.julialang.org/t/invokelatest-makes-code-run-slower/6027/1 "2017-09-21T15:44:58Z")

</div>

It seems that when I upgraded the [Fatou](https://github.com/chakravala/Fatou.jl) to julia 0.6 from 0.5, I needed to work around the new world counting feature in the julia language. It was possible to make Fatou functional in 0.6 by using the new `invokelatest()` function in the places where it was needed to run newly generated code.

However, this change significantly affects the computing time required by `2x`.

This can be easily demonstrated by running the `Pkg.test("Fatou")` command:

In julia 0.6

```nohighlight
julia> Pkg.test("Fatou")
INFO: Testing Fatou
Fatou detected 4 julia threads.
  0.680028 seconds (1.27 M allocations: 45.425 MiB, 4.22% gc time)
  0.325977 seconds (1.17 M allocations: 34.818 MiB, 2.54% gc time)
  0.348296 seconds (1.17 M allocations: 35.009 MiB, 4.45% gc time)
INFO: Fatou tests passed

```

However, in julia 0.5.2 the code is able to run faster:

```nohighlight
julia> Pkg.test("Fatou")
INFO: Testing Fatou
Fatou detected 4 julia threads.
  0.313702 seconds (566.66 k allocations: 15.841 MB, 3.38% gc time)
  0.165542 seconds (913.34 k allocations: 24.549 MB, 4.70% gc time)
  0.264221 seconds (629.58 k allocations: 17.135 MB, 3.39% gc time)
INFO: Fatou tests passed

```

Is this a natural consequence of the world counting and invokelatest features? Is this something for which the performance can be improved still within the julia langauge? Is there something I am overlooking on my end that would help me speed it up again?

Regards,

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [September 21, 2017, 3:46pm UTC](https://discourse.julialang.org/t/invokelatest-makes-code-run-slower/6027/2 "2017-09-21T15:46:54Z")

</div>

> [@"running in world age X, while current world is Y" errors](https://discourse.julialang.org/t/running-in-world-age-x-while-current-world-is-y-errors/5871/4):
>
> No, simply defining the same function twice wouldn’t cause this — you can try it by modifying the task example I have above. In your case, the problem is likely the same as the simpler example in the documentation: [Redefining Methods](https://docs.julialang.org/en/stable/manual/methods/#Redefining-Methods-1). You’re evaluating code and defining new methods and then trying to call those new methods, but the code that is doing that is still frozen in the old world from when it started running. Yes, invokelatest is definitely slower. It has to emit very pessimized …

---

<div class="post-metadata">

**Author:** ![chakravala](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chakravala/32/6832_2.png) [@chakravala](https://discourse.julialang.org/u/chakravala)\
**Post date:** [September 21, 2017, 3:53pm UTC](https://discourse.julialang.org/t/invokelatest-makes-code-run-slower/6027/3 "2017-09-21T15:53:51Z")

</div>

So there is no way that the julia language could accept more specific information (theoretically) about the types in the new function, in order to speed up performance of such a function call? The programmer might know this information, the julia language would just have to be able to accept that information in order to anticipate the types correctly.

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [September 21, 2017, 3:59pm UTC](https://discourse.julialang.org/t/invokelatest-makes-code-run-slower/6027/4 "2017-09-21T15:59:41Z")

</div>

You could manually add type-assertions that allow Julia to make stronger assumptions about what the new versions of the function may return.

---

<div class="post-metadata">

**Author:** ![chakravala](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chakravala/32/6832_2.png) [@chakravala](https://discourse.julialang.org/u/chakravala)\
**Post date:** [September 21, 2017, 9:23pm UTC](https://discourse.julialang.org/t/invokelatest-makes-code-run-slower/6027/5 "2017-09-21T21:23:45Z")

</div>

What source files in the julia code base would I need to look at if I wanted to try to implement this?

---

<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 21, 2017, 9:40pm UTC](https://discourse.julialang.org/t/invokelatest-makes-code-run-slower/6027/6 "2017-09-21T21:40:22Z")

</div>

Your own code?

---

<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 21, 2017, 9:42pm UTC](https://discourse.julialang.org/t/invokelatest-makes-code-run-slower/6027/7 "2017-09-21T21:42:08Z")

</div>

Also why do you claim it’s the `invokelatest` that’s causing the issue?

---

<div class="post-metadata">

**Author:** ![chakravala](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chakravala/32/6832_2.png) [@chakravala](https://discourse.julialang.org/u/chakravala)\
**Post date:** [September 21, 2017, 9:46pm UTC](https://discourse.julialang.org/t/invokelatest-makes-code-run-slower/6027/8 "2017-09-21T21:46:15Z")

</div>

As @mbauman pointed out, using the `invokelatest` feature in this way does cause the code to slow down, since the type information cannot be inferred. I’d like to fix this in my own code, but as far as I know, the julia language does not yet let me provide the required type information when calling the `invokelatest` function. So if julia can’t provide this feature yet, someone needs to implement it, right?

---

<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 21, 2017, 10:44pm UTC](https://discourse.julialang.org/t/invokelatest-makes-code-run-slower/6027/9 "2017-09-21T22:44:47Z")

</div>

> [@chakravala](#):
>
> As @mbauman pointed out, using the invokelatest feature in this way does cause the code to slow down

Well, it’ll slow down compare to if you didn’t do runtime code generation. It won’t be slower than what you would otherwise get on \<=0.5

> [@chakravala](#):
>
> the julia language does not yet let me provide the required type information when calling the invokelatest function

It does by

> [@mbauman](#):
>
> You could manually add type-assertions that allow Julia to make stronger assumptions about what the new versions of the function may return.

---

<div class="post-metadata">

**Author:** ![chakravala](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chakravala/32/6832_2.png) [@chakravala](https://discourse.julialang.org/u/chakravala)\
**Post date:** [September 21, 2017, 11:07pm UTC](https://discourse.julialang.org/t/invokelatest-makes-code-run-slower/6027/10 "2017-09-21T23:07:53Z")

</div>

Have a look here at my source code: [src/Fatou.jl](https://github.com/chakravala/Fatou.jl/blob/master/src/Fatou.jl#L258-L261)

```nohighlight
(sym2fun(invokelatest(K.Q,Sym(:a),Sym(:b)),:(Complex{Float64})) |> eval)::Function

```

I definitely provide the type information there `Complex{Float64}`, which is an argument to my `sym2fun` equation that generates the code that gets evaluated.

Using `sym2fun` defined in [src/internals.jl](https://github.com/chakravala/Fatou.jl/blob/master/src/internals.jl) I build the function expression that I need to run, it accepts a `SymPy.Sym` and a `type` as an argument

```nohighlight
sym2fun(expr,typ) = Expr(:function, Expr(:call, gensym(),
        map(s->Expr(:(::),s,typ),sort!(Symbol.(free_symbols(expr))))..., Expr(:(...),:zargs)),
SymPy.walk_expression(expr))

```

The argument I feed into this is `invokelatest(K.Q,Sym(:a),Sym(:b))`, which plugs SymPy symbols into the arguments of `K.Q` so that the julia expression can be constructed using the correct type information.

The function `h` defined like this is then used in another function called `nf`

```nohighlight
function nf(z0::Complex{Float64})::Tuple{UInt8,Complex{Float64}}
        K.mandel ? (z = K.seed): (z = z0); zn = 0x00
        while (K.newt ? (h(z,z0)::Float64>K.ϵ)::Bool : (h(z,z0)::Float64<K.ϵ))::Bool && K.N>zn
            z = f(z,z0)::Complex{Float64}; zn+=0x01
        end; #end
        # return the normalized argument of z or iteration count
        return (zn::UInt8,z::Complex{Float64})::Tuple{UInt8,Complex{Float64}}
end

```

Then I evaluate this function and use it in the main [loop](https://github.com/chakravala/Fatou.jl/blob/master/src/Fatou.jl#L282-L283)

```nohighlight
@time @threads for j = 1:length(y); for k = 1:length(x);
    (matU[j,k],matF[j,k]) = invokelatest(nf,Z[j,k]); end; end

```

As you can see, I have provided the necessary type information, which resulted in fast code in julia 0.5, however is slower by merely introducing `invokelatest` into the code for julia 0.6.

How am I supposed to provide this type information in julia 0.6 then, if it is possible?

---

<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 21, 2017, 11:13pm UTC](https://discourse.julialang.org/t/invokelatest-makes-code-run-slower/6027/11 "2017-09-21T23:13:16Z")

</div>

I know this is unintuitive but the type information you are providing is useless. The compiler can figure out those perfectly fine (assuming the code are properly generated). Even if compiler couldn’t figure out these info by itself, these uses of type assertions are as useful in 0.6+ with invokelatest as they where in \<=0.5.

The type info that the compiler can’t figure out (and it can’t in either case) is the return type of the `invokelatest`. You just need a type assert there. There should be no other difference.

That’s why I asked if you know the issue is caused by invokelatest since that shouldn’t be the obvious issue.

---

<div class="post-metadata">

**Author:** ![chakravala](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chakravala/32/6832_2.png) [@chakravala](https://discourse.julialang.org/u/chakravala)\
**Post date:** [September 21, 2017, 11:23pm UTC](https://discourse.julialang.org/t/invokelatest-makes-code-run-slower/6027/12 "2017-09-21T23:23:28Z")

</div>

Yes, that makes sense, thanks for clarifying. Previously, having the type assertion at the return value of the function was sufficient to provide the output type. Now it was necessary to assert it in the function call as well:

```nohighlight
(matU[j,k],matF[j,k]) = invokelatest(nf,Z[j,k])::Tuple{UInt8,Complex{Float64}}

```

and this change now returns the performance to be approximately equal to the 0.5 performance.

```nohighlight
julia> Pkg.test("Fatou")
INFO: Testing Fatou
Fatou detected 4 julia threads.
  0.397973 seconds (873.64 k allocations: 26.022 MiB, 2.88% gc time)
  0.180062 seconds (1.01 M allocations: 27.105 MiB, 4.29% gc time)
  0.185982 seconds (984.80 k allocations: 26.750 MiB, 4.13% gc time)
INFO: Fatou tests passed

```

Also, I realize that some of my extra type assertions are useless, but it also helps me as a programmer to precisely think through the data flow of my program, so it doesn’t hurt to have it in there.

Well, that does solve that issue then.

---

<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 21, 2017, 11:27pm UTC](https://discourse.julialang.org/t/invokelatest-makes-code-run-slower/6027/13 "2017-09-21T23:27:18Z")

</div>

> [@chakravala](#):
>
> but it also helps me as a programmer to precisely think through the data flow of my program

It’s mostly personal tastes but I should say that having extra type assertion sometimes makes the code hard to read simply because they are distracting.  
That said, you know how to write code that you can most easily read and yes those doesn’t hurt as far as runtime performance is concerned (the compiler will need to optimize them out but that’s usually a pretty cheap transformation).

---

<div class="post-metadata">

**Author:** ![chakravala](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chakravala/32/6832_2.png) [@chakravala](https://discourse.julialang.org/u/chakravala)\
**Post date:** [September 21, 2017, 11:57pm UTC](https://discourse.julialang.org/t/invokelatest-makes-code-run-slower/6027/14 "2017-09-21T23:57:10Z")

</div>

Gotcha, yea it’s not my preferred taste either for most programming I typically do. Could you elaborate on why the compiler needs to optimize the unecessary type assertions out?

---

<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 22, 2017, 12:43am UTC](https://discourse.julialang.org/t/invokelatest-makes-code-run-slower/6027/15 "2017-09-22T00:43:56Z")

</div>

All constructs in the code has a defined behavior and so the compiler/runtime need to do exactly that. Of course if the compiler can predict what it does it can maybe replace it with something simpler. Basically the more complicated the code you write, the more work the compiler has to do to reduce it, nothing more complicated. It’s not really relavant and I’m just saying that 0 runtime cost != 0 cost.
