# Why is there a performance difference between global and local variables in non-interactive Julia programs?

**URL:** https://discourse.julialang.org/t/why-is-there-a-performance-difference-between-global-and-local-variables-in-non-interactive-julia-programs/5753
**Category:** General Usage
**Tags:** performance
**Created:** [September 6, 2017, 11:55pm UTC](https://discourse.julialang.org/t/why-is-there-a-performance-difference-between-global-and-local-variables-in-non-interactive-julia-programs/5753 "2017-09-06T23:55:17Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![tparker](https://avatars.discourse-cdn.com/v4/letter/t/839c29/32.png) [@tparker](https://discourse.julialang.org/u/tparker)
#### Post date: [September 6, 2017, 11:55pm UTC](https://discourse.julialang.org/t/why-is-there-a-performance-difference-between-global-and-local-variables-in-non-interactive-julia-programs/5753/1 "2017-09-06T23:55:17Z")

</div>

I’ve found two places in the documentation that say that local is better than than global in terms of performance: [Performance Tips](https://docs.julialang.org/en/latest/manual/performance-tips/) says

> A global variable might have its value, and therefore its type, change at any point. This makes it difficult for the compiler to optimize code using global variables. Variables should be local, or passed as arguments to functions, whenever possible.
> 
> Any code that is performance critical or being benchmarked should be inside a function.
> 
> We find that global names are frequently constants, and declaring them as such greatly improves performance.

Similarly, [Constants](https://docs.julialang.org/en/stable/manual/variables-and-scoping.html#Constants-1) says

> The const declaration is allowed on both global and local variables, but is especially useful for globals. It is difficult for the compiler to optimize code involving global variables, since their values (or even their types) might change at almost any time. If a global variable will not change, adding a const declaration solves this performance problem.
> 
> Local constants are quite different. The compiler is able to determine automatically when a local variable is constant, so local constant declarations are not necessary for performance purposes.

For interactive sessions in the REPL, I understand how global variables really do need to be kept general, because they could change at any time. But for non-interactive sessions, the distinction between global and local variables seems rather artificial - by placing the _entire_ code inside some function `main` and then calling `main` from global scope, all global variables can be converted into formally local ones. This would seem to eliminate the performance problems with global variables and with performance-critical code outside of any functions. Why doesn’t Julia do this automatically?

---

<div class="post-metadata">

### Author: ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)
#### Post date: [September 7, 2017, 12:05am UTC](https://discourse.julialang.org/t/why-is-there-a-performance-difference-between-global-and-local-variables-in-non-interactive-julia-programs/5753/2 "2017-09-07T00:05:01Z")

</div>

> [@tparker](#):
>
> For interactive sessions in the REPL, I understand how global variables really do need to be kept general, because they could change at any time. But for non-interactive sessions, the distinction between global and local variables seems rather artificial - by placing the entire code inside some function main and then calling main from global scope, all global variables can be converted into formally local ones. This would seem to eliminate the performance problems with global variables and with performance-critical code outside of any functions. Why doesn’t Julia do this automatically?

No the fundamental difference is that `eval` can observer and mutate global variables but not local variables. Since the sideeffect of `eval` is undecidable it’s impossible to “convert global variable into local ones”. You can of course speculate and that’s what other JIT does but you can’t do that as a semantically sound transformation.

---

<div class="post-metadata">

### Author: ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)
#### Post date: [September 7, 2017, 12:07am UTC](https://discourse.julialang.org/t/why-is-there-a-performance-difference-between-global-and-local-variables-in-non-interactive-julia-programs/5753/3 "2017-09-07T00:07:12Z")

</div>

> [@tparker](#):
>
> But for non-interactive sessions, the distinction between global and local variables seems rather artificial - by placing the entire code inside some function main and then calling main from global scope, all global variables can be converted into formally local ones. This would seem to eliminate the performance problems with global variables and with performance-critical code outside of any functions. Why doesn’t Julia do this automatically?

This sounds promising, but the trivial implementation described here would actually break some codes. One example is with `eval`. If you do `@eval a=2` then because `eval` is dynamic this takes place in the global (module) scope. So `a` gets added to the module, not the function. You’d need to `global a` to get the global `a` if you also had a local `a`, so this is different because in the global scope this would have changed the value of `a` instead of making a new one in a different scope.

However, a fancier version of what you’re describing could work if it works around all of these issues automatically by parsing? I’m not sure if that’s possible, but it would be interesting to look into. I’m sure there’s a counter example where it would have a difference that cannot be determined by parsing, like evaling a mutating function will mutate the global which will then not be in a local of the same name or something like that.

---

<div class="post-metadata">

### Author: ![tparker](https://avatars.discourse-cdn.com/v4/letter/t/839c29/32.png) [@tparker](https://discourse.julialang.org/u/tparker)
#### Post date: [September 7, 2017, 12:21am UTC](https://discourse.julialang.org/t/why-is-there-a-performance-difference-between-global-and-local-variables-in-non-interactive-julia-programs/5753/4 "2017-09-07T00:21:07Z")

</div>

@ChrisRackauckas I see, I was not aware of that subtlety involving `eval`. Is the documentation’s claim that “local constant declarations are not necessary for performance purposes” unconditionally true, regardless of how complicated the function in which it’s declared is?

---

<div class="post-metadata">

### Author: ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)
#### Post date: [September 7, 2017, 12:25am UTC](https://discourse.julialang.org/t/why-is-there-a-performance-difference-between-global-and-local-variables-in-non-interactive-julia-programs/5753/5 "2017-09-07T00:25:44Z")

</div>

> [@ChrisRackauckas](#):
>
> However, a fancier version of what you’re describing could work if it works around all of these issues automatically by parsing?

No non-speculative version can work without change of semantics. Changing the semantics is almost not an option since it breaks the separation between having maximum flexibility in global scope while having only features that does not break optimizations in local scope (so the features you didn’t use in the local scope will always have zero effect on performance). Implementing a speculative version is possible and is done in basically all other jit’s as I said but it’s of very low priority since we’ll unlikely work on that before we fully optimizes the code that we actually care about (i.e. local scope).

> [@tparker](#):
>
> local constant declarations are not necessary for performance purposes” unconditionally true, regardless of how complicated the function in which it’s declared is?

Local constants are not allowed now (deprecated) and had no effect (it was being ignored).  
It does not affect the inferrability of the use of the variable since the compiler can see everything about it (no matter how long the function is) and can only affect error finding.
