# Julia v1.8 -\> v1.9 makes this code 1000x slower

**URL:** <https://discourse.julialang.org/t/julia-v1-8-v1-9-makes-this-code-1000x-slower/99766>\
**Category:** Performance\
**Created:** [June 2, 2023, 12:20pm UTC](https://discourse.julialang.org/t/julia-v1-8-v1-9-makes-this-code-1000x-slower/99766 "2023-06-02T12:20:01Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![user664303](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/user664303/32/37843_2.png) [@user664303](https://discourse.julialang.org/u/user664303)\
**Post date:** [June 2, 2023, 12:20pm UTC](https://discourse.julialang.org/t/julia-v1-8-v1-9-makes-this-code-1000x-slower/99766/1 "2023-06-02T12:20:01Z")

</div>

On upgrading to Julia from 1.8.5. to 1.9.0 I noticed code in one of my packages slow down significantly. It has taken me a long time to get down to the simplest code which replicates the problem, but I have it now. After upgrading, the following code has become type unstable, and 1000x slower as a result:

```julia
using StaticArrays, BenchmarkTools

@inline function countvars(bitflags, var)
    return bitflags >> 0
end

function myfunc(::Val{bitflags}, var) where bitflags
    N = countvars(bitflags, var)
    return zeros(SVector{N, Float64})
end

struct A
    data::Float64
end
a = A(0.)

@btime myfunc(Val(1), $a);
@code_warntype myfunc(Val(1), a);

```

Moreover, this effect is very unstable - seemingly insignificant changes to the code result in the type stability disappearing. For example:

- Removing `data` from struct `A`
- Moving the code from `countvars` directly into `myfunc`
- Removing the redundant `var` from the inputs to `countvars`
- Changing the `>>` in line 4 to something like `&` or `+`

I have raised [an issue about this](https://github.com/JuliaLang/julia/issues/50037) in GitHub, but wanted to see if anyone else had seen anything similar. Is this expected, or unexpected?

---

<div class="post-metadata">

**Author:** ![jmair](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jmair/32/35117_2.png) [@jmair](https://discourse.julialang.org/u/jmair)\
**Post date:** [June 2, 2023, 12:46pm UTC](https://discourse.julialang.org/t/julia-v1-8-v1-9-makes-this-code-1000x-slower/99766/2 "2023-06-02T12:46:26Z")

</div>

I imagine this is something to do with constant propagation. To be explicit you could try:

```julia
@inline Base.@constprop :aggressive function countvars(bitflags, var)
    return bitflags >> 0
end

```

EDIT: Corrected the syntax thanks to @aviatesk, but still doesn’t seem to change anything.

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [June 2, 2023, 12:48pm UTC](https://discourse.julialang.org/t/julia-v1-8-v1-9-makes-this-code-1000x-slower/99766/3 "2023-06-02T12:48:35Z")

</div>

Yeah, that’s really weird. I can confirm the regression exists on master as well. One minor simplification is to change `myfunc` to

```julia
function myfunc(::Val{bitflags}, var) where bitflags
    N = countvars(bitflags, var)
    return Array{Float64, N}
end

```

which removes the dependency on `StaticArrays`. The part of this that makes no sense to me is that the compiler knows that `countvars` is constant foldable, but for some reason isn’t constant folding it.

---

<div class="post-metadata">

**Author:** ![aviatesk](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aviatesk/32/7610_2.png) [@aviatesk](https://discourse.julialang.org/u/aviatesk)\
**Post date:** [June 2, 2023, 12:51pm UTC](https://discourse.julialang.org/t/julia-v1-8-v1-9-makes-this-code-1000x-slower/99766/4 "2023-06-02T12:51:21Z")

</div>

> [@jmair](#):
>
> `N = Base.@constprop :aggressive countvars(bitflags, var)`

This is not a valid `Base.@constprop` annotation. `Base.@constprop` can only be applied on a method definition, not on callsites. And the `@inline` annotation is enough to encourage constant propagation.

> [@Oscar\_Smith](#):
>
> I can confirm the regression exists on master as well.

Really? I think it only exists on 1.9 only. And it looks like something about semi-concrete abstract interpretation. Since we add many refinements on it after branching on 1.9, I guess the inference regression has been resolved on 1.10 but still there for 1.9.

---

<div class="post-metadata">

**Author:** ![user664303](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/user664303/32/37843_2.png) [@user664303](https://discourse.julialang.org/u/user664303)\
**Post date:** [June 2, 2023, 12:51pm UTC](https://discourse.julialang.org/t/julia-v1-8-v1-9-makes-this-code-1000x-slower/99766/5 "2023-06-02T12:51:26Z")

</div>

> [@jmair](#):
>
> ```julia
> function myfunc(::Val{bitflags}, var) where bitflags
> N = Base.@constprop :aggressive countvars(bitflags, var)
> return zeros(SVector{N, Float64})
> end
> 
> ```

This throws an error for me:

`ERROR: LoadError: countvars(bitflags, var) is not a function expression`

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [June 2, 2023, 12:54pm UTC](https://discourse.julialang.org/t/julia-v1-8-v1-9-makes-this-code-1000x-slower/99766/6 "2023-06-02T12:54:05Z")

</div>

I see it on a 10 day old master.

---

<div class="post-metadata">

**Author:** ![user664303](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/user664303/32/37843_2.png) [@user664303](https://discourse.julialang.org/u/user664303)\
**Post date:** [June 6, 2023, 12:55pm UTC](https://discourse.julialang.org/t/julia-v1-8-v1-9-makes-this-code-1000x-slower/99766/7 "2023-06-06T12:55:52Z")

</div>

I have found another performance regression moving from Julia v1.8.5 to v1.9.0. Some code now allocates memory, when none was allocated using v1.8.5. This makes the code 5x slower. There doesn’t appear to be any type instability. I have created [an issue here](https://github.com/JuliaLang/julia/issues/50073).

Is there any information on what has changed? I guess it some under-the-hood compiler inference algorithms.
