To global or not to global!

Started by
20 comments, last by nuclear123 12 years, 11 months ago
What usually signifies a good candidate for a global variable? From a performance standpoint
Advertisement
From a performance standpoint; none.

Globals cause a number of bad things to happen;

- at the compiler level they can kill all manner of optimisations as the compiler can't make assumptions about the state of the data when reading it
- at the CPU level global data is unlikely to be in a cache on first access which means you are going to cause a cache miss (which hurts) and the load will remove a cache line which can hurt you later if you happen to access data which was in that cache line.
If the performance overhead of it not being a global is higher than the performance overhead of it being a global. ;)

Seriously, the answer is only half-facetious. This is one of those things that you're going to have to profile on a per-application basis (and my bet is that in the most common usage scenarios you won't notice any difference at all - we're talking serious micro-optimization here).

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.

Globals might cause bad things to happen, and might confuse optimizations performed by the compiler. But using namespaces in a good manner can prevent this. Global variables t3n? to conflict with the least knowledge principle, although it doesn't neccessarily do that. You cannot decide what your CPU leaves on the cache directly through C++, for instance, and global variables rarely used are obviously less likely to be there, as are any other rarely-used variable. I think using the cache as an argument against global variables is a little out there... :-/

In general you should be better off using global variables performance wise. The issues seen or avoided with global variables are typically design-wise.

Globals cause a number of bad things to happen;

- at the compiler level they can kill all manner of optimisations as the compiler can't make assumptions about the state of the data when reading it
- at the CPU level global data is unlikely to be in a cache on first access which means you are going to cause a cache miss (which hurts) and the load will remove a cache line which can hurt you later if you happen to access data which was in that cache line.


they are also concurrency hell for similar reasons to number 1 except instead of just making the compiler work harder it will make whoever is debugging your program want to kill you; even if it is yourself.

edit: before it comes up, singletons are globals too so don't use those either.

Globals might cause bad things to happen, and might confuse optimizations performed by the compiler. But using namespaces in a good manner can prevent this.


Even then, if the data is at a scope where it can be touched from multiple locations then the compiler has to assume that it's state is 'unknown' which disables optimisations on both that access AND anything which relies on it which could have otherwise been performed.


You cannot decide what your CPU leaves on the cache directly through C++, for instance, and global variables rarely used are obviously less likely to be there, as are any other rarely-used variable. I think using the cache as an argument against global variables is a little out there... :-/
[/quote]

You are correct in that you can't directly control it however keeping things local and access data in certain ways can guide it much better. You are right that 'rarely used variables' are not likely to be in the cache either but they will be warmed as your code passes over them (and correctly arranging your data can help keep the cache warmed as well by letting the CPU pre-fetch it) and this is all aided by scope.

Caring about the cache is certainly not 'out there' when someone says 'performance'. Memory access is slow, therefore caring about your cache and what bad things you are doing to it is important.


In general you should be better off using global variables performance wise. The issues seen or avoided with global variables are typically design-wise.
[/quote]

No, in general you will be worse off because they disable optimisations and hurt your cache usage. If they get used or not tends to be a matter of design and pragmatism ("We could make this non-global but we don't have the time") and not solid engineering.

[quote name='phantom' timestamp='1305036435' post='4808959']
Globals cause a number of bad things to happen;

- at the compiler level they can kill all manner of optimisations as the compiler can't make assumptions about the state of the data when reading it
- at the CPU level global data is unlikely to be in a cache on first access which means you are going to cause a cache miss (which hurts) and the load will remove a cache line which can hurt you later if you happen to access data which was in that cache line.


they are also concurrency hell for similar reasons to number 1 except instead of just making the compiler work harder it will make whoever is debugging your program want to kill you; even if it is yourself.
[/quote]

I beg to differ. I've seen developers writing code with a high degree of concurrency while avoiding global variables. -While minimalistic module knowledge and overlap, and well seperated namespaces can keep concurrent operation very low.

So although your mentioned case may, with respect, be more frequent, it's actually possible to avoid with globals, if implemented properly. Against popular practice and belief. :)

[quote name='way2lazy2care' timestamp='1305037762' post='4808973']
they are also concurrency hell for similar reasons to number 1 except instead of just making the compiler work harder it will make whoever is debugging your program want to kill you; even if it is yourself.


I beg to differ. I've seen developers writing code with a high degree of concurrency while avoiding global variables. -While minimalistic module knowledge and overlap, and well seperated namespaces can keep concurrent operation very low.

So although your mentioned case may, with respect, be more frequent, it's actually possible to avoid with globals, if implemented properly. Against popular practice and belief. :)
[/quote]

Everything is good "if implemented properly." The point is that it is un-necessary, and if not implemented properly, which is most likely the case, will cause a lot of heart ache.

In the case of globals, you will either not use them in your concurrent parts of your program, which isn't using them concurrently in the first place, or you will lock them, which will hurt performance, or you will get unpredictable states of your objects, which is also bad.

While it is possible to implement a concurrent program with global variables well, there will be a way to solve the problem without global variables that will either be safer, perform better, or be more accurate.
Okay, I might need a lil' more convincing from you, Phantom:
How does a given compiler differentiate optimizations on my_namespace :: my_var compared to my_object.my_var?

Because I don't get the performance penaulty in that.

Also, I practice using functions nested in suitable namespaces, which are reachable from the global scope, so I might have overstated the equal benefits of Oo vs global variables, clearly non-global variables are better design-wise, but there are exceptions, obviously.

Okay, I might need a lil' more convincing from you, Phantom:
How does a given compiler differentiate optimizations on my_namespace :: my_var compared to my_object.my_var?

Because I don't get the performance penaulty in that.

Also, I practice using functions nested in suitable namespaces, which are reachable from the global scope, so I might have overstated the equal benefits of Oo vs global variables, clearly non-global variables are better design-wise, but there are exceptions, obviously.


I think this is vaguely how it works. Phantom can probably elaborate though.

When you pass an object to a function it will probably prefetch variables belonging to the object, so they will already be on the cache when you need them, whereas when you do it with globals it will have to fetch the global from memory every time it needs it.

Because it is a single variable/object you will probably not be optimizing the potential ability for your memory fetching as you will be grabbing small bits of data when you could be grabbing large blobs of data in a single fetch.

This topic is closed to new replies.

Advertisement