I am following along in Adrian Salceanu’s book “Julia Programming Projects”. He is on Julia 1.0 and I am using 1.4. He says that running in the global scope is slower than wrapping in a function because the function is pre-compiled and cites the following toy example:
julia> @time [x for x in 1:1_000_000];
0.031727 seconds (55.85 k allocations: 10.387 MiB)julia> function onetomil()
[x for x in 1:1_000_000]
end
onetomil (generic function with 1 method)
julia> @time onetomil();
0.027002 seconds (65.04 k allocations: 10.914 MiB)
When I run the above code in the REPL I get 0.0023 consistently for the first (global-scope) example and variable speeds of between 0.0023 and 0.005 for the function. Assuming that this must be because I have a better/more modern machine than the author’s I upped the run to 1:1_000_000_000. Now I get runs of 2.44 seconds for the global-scope test and 2.99 seconds for the function-wrapped example (I can’t go any higher than that as I get an out of memory error).
So I must conclude that either there’s been a massive performance boost in list comprehension between v 1.0 and 1.4 and/or 1.4 is generally so fast as there is no discernible difference. What I can’t conclude is that wrapping the code in a function is really faster than using the global scope. Can anybody help me understand these results?
EDIT:
I did some more tests. I ditched the list comprehension as being too efficient and opted (for the purposes of the test only) to use a for loop and push each value to an initially empty array. As expected the for loop was significantly slower. A loop of 10_000_000 took 1.07 seconds in global scope and only 0.47 seconds when wrapped in a function (code below).
x = [ ]
@time for i in 1: 10_000_000
push!(x, i)
endfunction loopy()
x = [ ]
for for i in 1: 10_000_000
push!(x, i)
end
end
@time loopy()
So, I thought I’d proved not using global scope is indeed quicker. BUT, I then upped the loop to 1_000_000_000 as before expecting to see a bigger divergence. Global scope took 8.57 seconds but the function gave vary variable results again between 9.16 and 12.15 seconds - again slower than global scope.
I am back to “the jury is out” on whether functions are really faster than global scope and speeds get flaky when in a function. What is happening here? Why can’t I see functions being faster than using the global scope?
EDIT #2
Tried the same with @btime and conclusively proved that running in a function is slightly slower than running in global scope! Using the for-loop with a range of 10_000_000, @btime records the global scope loop at 878.8ms (152.58 MiB) and 2.334s (281.58 MiB) for the same loop wrapped in a function.