Back in the day I had trouble convincing my C++ friends to give Julia a try, because Julia's garbage collector was a showstopper. But if you follow these performance tips related to pre-allocation, in-place mutation, avoiding temporary allocations (and maybe avoiding cycling references), you don't struggle with GC performance issues.
Looking back, I think the tooling Julia had from the start, combined with the REPL, made it actually really nice to fix these performance issues. Much better than compiling and linking a binary and running it through some heap profiler tool. You could simply do
julia> @time f()
x.y seconds (N allocations: M bytes)
and iteratively improve part of the code base instead of profiling the entire application.
(To be fair: back then escape analysis was not implemented in the compiler, and it was hard to avoid silly allocations)
For newcomers my main tip is to use views for array slices (for example, via the @view and @views macros), since by default Julia creates copies of slices. Broadcast operation (the dot syntax) is another super useful instrument for speeding up vectorized operations. You can write fast GPU code with them without resorting to GPU kernels, in some cases. Although GPU kernel programming via CUDA.jl is convenient in Julia, once you get used to it.
We have been running benchmarks to compare different languages relevant to high-performance computing and unfortunately Julia still lags behind even Numba-JIT-compiled Python. Perhaps my understanding of Julia is limited, but even the Rodinia SRAD program, which was originally written in Julia, performs faster in all other implementations that aren't Julia.
9 comments
[ 3.0 ms ] story [ 32.5 ms ] thread[1] https://modernjuliaworkflows.org/optimizing/
Looking back, I think the tooling Julia had from the start, combined with the REPL, made it actually really nice to fix these performance issues. Much better than compiling and linking a binary and running it through some heap profiler tool. You could simply do
and iteratively improve part of the code base instead of profiling the entire application.(To be fair: back then escape analysis was not implemented in the compiler, and it was hard to avoid silly allocations)
In retrospect, the PhD experience was miserable and using Julia contributed to my 'death by a thousand cuts'.