Julia DISCUSSION

My Julia loop is far slower than expected: how do I find type instability and global variable problems?

Started by shahira Julia performancetype stabilityglobal variablescode_warntypeBenchmarkTools
5 replies 248 views 6 participants
Latest activity · 30 Sep 2026

My Julia loop is far slower than expected: how do I find type instability and global variable problems?

shahira Julia Forum
#1

I translated a numerical loop from C to Julia expecting similar speed. It sums a function over a Vector{Float64} of 10 million samples, written as a script at top level with the data and a couple of parameters as ordinary variables. @time reports millions of allocations, which I did not expect from a loop that only adds numbers.

What are the usual reasons for this, and which tools show where the time and the allocations come from?

Community replies 5

Re: My Julia loop is far slower than expected: how do I find type instability and global variable problems?

#2

The most common cause is exactly what you describe: the loop runs at top level and reads non-constant global variables. A global can be rebound to a value of any type at any time, so the compiler cannot assume its type; every use becomes a dynamic lookup with boxed intermediate values, and those are your allocations.

Put the work in a function and pass the data in as arguments: function total(x, gain) ... end. Julia compiles a specialised version of a function for the concrete argument types it is called with, which is where the speed comes from. For values that really are constant, declare them const.

Re: My Julia loop is far slower than expected: how do I find type instability and global variable problems?

#3

The second cause is type instability inside the function: a variable whose type changes. The classic case is s = 0 followed by s += x[i] with Float64 data; s starts as an Int and becomes a Float64. Initialise with s = zero(eltype(x)) or 0.0. Another is a function that returns an Int on one branch and a Float64 on another.

@code_warntype total(x, 2.0) prints the inferred types; anything shown as Any or as a large Union in the body is a place where the compiler lost track.

Re: My Julia loop is far slower than expected: how do I find type instability and global variable problems?

#4

Measure carefully, otherwise you will be timing the compiler. The first call of a function includes its compilation, so call it once and time the second call, or use the BenchmarkTools package: @btime total($x, $gain). The $ interpolates the globals so that the benchmark itself does not suffer from the global variable problem.

A numeric loop over a Vector{Float64} should report 0 allocations. If @btime still shows allocations proportional to the number of iterations, there is an instability left.

Re: My Julia loop is far slower than expected: how do I find type instability and global variable problems?

#5

Check the element types of your containers as well. Vector{Float64} stores the numbers inline, 8 bytes each, so 10 million samples are one contiguous 80 MB block. Vector{Real} or Vector{Any} stores a pointer per element to a separately allocated value, and every access needs a type check. An array created with [] and filled with push! is a Vector{Any}; write Float64[] instead.

The same applies to struct fields: struct P; x::Real; end is slow for the same reason, while struct P{T<:Real}; x::T; end keeps the field concrete.

Re: My Julia loop is far slower than expected: how do I find type instability and global variable problems?

#6

Once the types are stable, the remaining gains are ordinary ones. Slices such as x[1:n] copy; use @views or view(x, 1:n) to avoid that. Julia arrays are column-major, so for a matrix the inner loop should run over the first index. Preallocate outputs and fill them with .= rather than creating new arrays in each iteration.

@inbounds removes bounds checks, but only add it after the loop is verified, since an out-of-range index then becomes undefined behaviour instead of an error.

TEP COMMUNITY