# Julia v1.9.0-beta2 is fast

**URL:** <https://discourse.julialang.org/t/julia-v1-9-0-beta2-is-fast/92290>\
**Category:** Performance\
**Created:** [December 29, 2022, 8:48pm UTC](https://discourse.julialang.org/t/julia-v1-9-0-beta2-is-fast/92290 "2022-12-29T20:48:32Z")\
**Posts on this page:** 1\
**Showing post:** 29

<div class="post-metadata">

**Author:** ![nilshg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nilshg/32/2283_2.png) [@nilshg](https://discourse.julialang.org/u/nilshg)\
**Post date:** [January 4, 2023, 12:18pm UTC](https://discourse.julialang.org/t/julia-v1-9-0-beta2-is-fast/92290/29 "2023-01-04T12:18:24Z")

</div>

Thought I’d leave this here as well: I wanted to get a feel for how the user experience of the “original” TTFX - i.e. time-to-first-plot using Plots.jl - has evolved over the years, so I wrote a little benchmark script that times starting Julia and running `using Plots; display(scatter(rand(1_000)))` for all Julia versions since 0.7.

Here’s what the mean and minimum times look like across versions:

![image](https://global.discourse-cdn.com/julialang/original/3X/5/d/5da2caf36ed83065f8bce497c69ea872222bc709.png)

Initially I had included 0.6.4 as well but with such an old Julia version one has to also fall back onto a very old Plots version which errors out on the `display` call. An alternative script with `savefig` instead of `display` suggests that 0.6 had similar TTFP to 0.7-1.2.

I think the plot makes clear the scale of achievement here - while I’m sure there’s more to come as the ecosystem starts to make best use of the new abilities of Julia, it seems clear that this is the first time that we’ve seen a dramatic qualitative shift in the sort of very basic experience that the modal user might have without resorting to any tricks like PackageCompiler.

Some more boring details for those interested below:

> **Details**
>
> The benchmarks were run on an i7 Windows laptop, `versioninfo()` is:
> 
> ```julia
> Platform Info:
> OS: Windows (x86_64-w64-mingw32)
> CPU: 8 × 11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz
> WORD_SIZE: 64
> LIBM: libopenlibm
> LLVM: libLLVM-13.0.1 (ORCJIT, tigerlake)
> Threads: 1 on 8 virtual cores
> 
> ```
> 
> As Plots.jl has dropped compatibility for older Julia versions over time, going back in Julia versions also means going back to older Plots versions, so the benchmarks don’t just capture differences in precompilation and other language features, but changes in Plots itself.
> 
> The following table shows the Plots version used for every Julia version, as well as the average, minimum, and standard deviation of the 20 samples taken:
> 
> ```plaintext
> │ String String Float64 Float64 Float64 
> ─────┼───────────────────────────────────────────────────
> 1 │ 0.6.4 0.17.4 11.5 10.7 0.9
> 2 │ 0.7.0 0.19.3 21.5 19.8 1.3
> 3 │ 1.0.5 1.4.3 18.5 18.1 0.5
> 4 │ 1.1.1 1.4.3 21.3 18.3 4.4
> 5 │ 1.2.0 1.4.4 22.8 21.4 1.5
> 6 │ 1.3.1 1.6.12 27.3 26.2 0.7
> 7 │ 1.4.2 1.6.12 35.0 30.0 5.4
> 8 │ 1.5.4 1.24.3 35.7 31.9 3.3
> 9 │ 1.6.5 1.27.6 24.6 21.7 2.4
> 10 │ 1.7.3 1.37.2 24.3 22.6 2.0
> 11 │ 1.8.3 1.38.0 20.6 17.7 2.8
> 12 │ 1.9.0b 1.38.0-dev 7.6 4.1 1.1
> 
> ```
> 
> Note that 1.9.0b uses a branch of Plots with a fix from Kristoffer that addresses an issue with the usage of cached code on Windows.
> 
> The whole benchmark code run is:
> 
> ```julia
> using DataFrames, ProgressMeter
> 
> path = "path/to/Julias"
> 
> julias = Dict(
> "0.6.4" => "Julia-0.6.4/bin/julia.exe",
> "0.7.0" => "Julia-0.7.0/bin/julia.exe",
> "1.0.5" => "Julia-1.0.5/bin/julia.exe",
> "1.1.1" => "Julia-1.1.1/bin/julia.exe",
> "1.2.0" => "Programs/Julia-1.2.0/bin/julia.exe",
> "1.3.1" => "Julia-1.3.1/bin/julia.exe",
> "1.4.2" => "Programs/Julia/Julia-1.4.2/bin/julia.exe",
> "1.5.4" => "Programs/Julia 1.5.4/bin/julia.exe",    
> "1.6.5" => "Programs/Julia-1.6.5/bin/julia.exe",
> "1.7.3" => "Programs/Julia-1.7.3/bin/julia.exe",
> "1.8.3" => "Programs/Julia-1.8.3/bin/julia.exe",
> "1.9.0b" => "Programs/Julia-1.9.0-beta2/bin/julia.exe",
> )
> 
> jdf = sort(DataFrame(version = collect(keys(julias)), location = collect(values(julias))), :version)
> 
> # Check versions
> for r ∈ eachrow(jdf)
> println("Julia version: ", r.version)
> if r.version == "0.6.4"
> run(`$(normpath(path, r.location)) -e "println(Pkg.installed()[\"Plots\"])"`);    
> else
> run(`$(normpath(path, r.location)) -e "import Pkg; println(Pkg.installed()[\"Plots\"])"`);
> end
> println()
> end
> 
> n = 20
> 
> jdf.times = [zeros(n) for _ ∈ 1:nrow(jdf)]
> 
> # Run code
> for r ∈ eachrow(jdf)
> println("Julia version: ", r.version)
> pn = normpath(path, r.location)
> @showprogress for i ∈ 1:n
> if r.version == "0.6.4"
> r.times[i] = @elapsed run(`$pn -e "using Plots; scatter(rand(1_000))"`);    
> else
> r.times[i] = @elapsed run(`$pn -e "using Plots; display(scatter(rand(1_000)))"`);    
> end
> end
> println()
> end
> 
> using Plots, Statistics
> 
> jdf.average = mean.(jdf.times)
> jdf.standard_dev = std.(jdf.times)
> 
> bar(jdf.version[2:end], jdf.average[2:end], label = "",
> linewidth = 0.1, ylabel = "Time (seconds)", xlabel = "Julia version",
> yticks = 0:5:50, 
> title = "Mean/minimum time for 20 samples\nusing Plots; display(scatter(rand(1_000)))")
> scatter!((1:nrow(jdf)-1) .- 0.5, minimum.(jdf.times)[2:end], label = "Minimum", markerstrokewidth = 0.1)
> 
> jdf.Plots_version = ["0.17.4", "0.19.3", "1.4.3", "1.4.3", "1.4.4", "1.6.12", 
> "1.6.12", "1.24.3", "1.27.6", "1.37.2", "1.38.0", "1.38.0-dev"]
> 
> select(jdf, :version, :average => (x -> round.(x, digits = 1)) => :average,
> :times => (x -> round.(minimum.(x), digits = 1)) => :minimum, 
> :times => (x -> round.(std.(x), digits = 1)) => :std_dev)
> 
> ```

---

_[View the full topic](https://discourse.julialang.org/t/julia-v1-9-0-beta2-is-fast/92290)._
