#!/usr/bin/env julia
using Random
if(length(ARGS)==1)
N=parse(Int64,ARGS[1])
else
N=1000
end
function play()
r=0
counter=0.0
while r<1.0
r+=rand(Float64)
counter+=1
end
return counter
end
function drive()
e=0.0
for i in 1:N
e+=play()
end
println(e/N)
end
@time drive()
with 15.485858 seconds (300.53 M allocations: 5.985 GiB, 0.59% gc time)
and
#!/usr/bin/env julia
using Random
function play()
r=0.0
counter=0.0
while r<1.0
r+=rand(Float64)
counter+=1.0
end
return counter
end
function drive(N::Int64)
e=0.0
for i in 1:N
e+=play()
end
println(e/N)
end
@time drive(length(ARGS)==1 ? parse(Int64,ARGS[1]) : 1000)
with 4.922885 seconds (468.38 k allocations: 21.594 MiB)
Why is the latter a factor three faster – or why does the former use so much memory?
Since N is a non const global it is possible for a value with a different type to get assigned to it. As a result Julia has to generate more generic code that is valid for potentially all types.
The answer to this should be that globals are fast as long as they are type annotated. Unfortunately, type annotated globals aren’t supported yet. There’s no great reason why not other than no one has implemented it yet.
You can define const globals, the type (and the value) of a const global is assumed to be unchanging. You only refer to a global after you define it. Consequently, const globals are de facto type annotated.
Do you mean: “we could have non-const fast globals in the future, their only restriction is that they cannot change type (but they could change value)”? We kinda already have that, you just need to make a global const N = Ref(parse(Int64,ARGS[1])) (the value is accessed by N[] and can be changed by N[] = new_value). Its type and value are constant (but its value is, in fact, a memory address), and the value pointed by the memory address can be changed safely, basically giving you a non-const type-annotated global.
what I mean is that i::int=0 doesn’t work in the global scope. If it did, you could have fast non-const globals since the compiler would know their type.
Global variables are a bad practice and should be avoided in any programming language.
For the rare occasions they are really needed the Ref syntax is available in Julia.
Even if there would be ways to generally speed up global variables in Julia, this would take up valuable time from the core devs and encourage bad programming styles.
Ironically, I would consider the Ref workaround shown above also bad programming style (more so as it is caused by non-const untyped globals being so slow).
And the only time use of global variables is really a bad practice is if you write code using globals where the code might get reused as a module, in which case the globals can cause trouble. For standalone scripts whose code will never get reused it’s no issue. The OP’s example of initializing a global variable Nin a standalone script is valid and it’s a shame that this have to be avoided due to performance consequences.
I am all for people adopting good programming practices and avoiding bad programming practices. I just hope they understand why they are considered either, instead taking advice that is never absolute as an absolute rule.