| Register | FAQ | Calendar | Search | Today's Posts | Mark Forums Read |
|
#1
| |||
| |||
| I need advice on when to use global and when not. I've always been taught to avoid useing globals as much as possible but recently since I've stepped into video game programming, I've heard that it's ok or "more accepted". I need a guideline for this matter, thanks. |
|
#2
| |||
| |||
| Andy White wrote: > I need advice on when to use global and when not. Not. Consider these two rules: - no global data variables - no public data members They are both simple ways to say a more important rule: Don't make primitive things globally writable. Suppose you have a function Foo(), and very far away is a function Bar(). Foo() changes the value of G, a global, and Bar() depended on the former value. If G makes Bar() have a bug, the source - Foo() - is not obvious because Foo() is very far away. (Worse, in a highly event-driven program like a game, the sequence of events that leads to Foo() and then eventually to Bar() might be very obscure and hard to reproduce.) The goal, when reading software, is to keep the chain of cause and effect as obvious as possible within a very short amount of text. That helps reduce the risk of bugs. So, put all raw data (int, string, float, etc.) inside objects, and make them private. Write methods on those objects named after their intent. Pass the objects around as reference parameters, and call their methods to get things done. Don't mess with an object's data members. Construct objects that are easy to use correctly and hard to break. > I've always been taught to > avoid useing globals as much as possible Why not post this question a generic programming group, like news:comp.object, or a group specific to your language? > but recently since I've stepped > into video game programming, I've heard that it's ok or "more accepted". I > need a guideline for this matter, thanks. Oh. Games should follow the same rules. Such rules are _more_ important in huge programs, because Foo() and Bar() could be so far apart. The two excuses for breaking such a simple rule are generally A> we have always done it like that, and B> it's faster, and we need that because we are Game Programmers. The first excuse leverages the author of Foo() also wrote Bar(), and we did not sack or transfer her or him yet. Design quality often gets as low as its original authors can comfortably still function in. (Lords know I have code like that.) Don't complain. The second excuse is completely invalid without an automated test to time that code and see if it's faster. In C++, if you hide global data in a Singleton Pattern object, and if its data members have inline Get() methods, then your compiler will produce (generally) the same opcodes to access the raw data as if it were naked. Further, 'inline' is not a magic keyword that automatically makes everything faster. Sometimes an out-of-line method is faster. Only time tests can tell. -- Phlip http://industrialxp.org/community/bi...UserInterfaces |
|
#3
| |||
| |||
| Having global variables is faster than having to pass the variable round from function to function. I would say if your going to use them keep use a global_ prefix so as not to get local and global variables confused. eg global_lives_remaining; I use a global array of 3D objects to make my 3D engine run faster; items in a global array can be referenced as integers (usually) therefore i can do not have to pass a long pointer into a function specifying the address of the array in memory - therefore saving on memory management; some functions may be called a hundred times per frame so every optimisation counts! ...nokturnal |
|
#4
| |||
| |||
| In article <Uom4e.29323$hU7.25453@newssvr33.news.prodigy.com> , Phlip <phlip_cpp@yahoo.com> wrote: >The second excuse is completely invalid without an automated test to >time that code and see if it's faster. In C++, if you hide global >data in a Singleton Pattern object, and if its data members have >inline Get() methods, then your compiler will produce (generally) >the same opcodes to access the raw data as if it were naked. True only when the accessor exists in a header. And only when you have inlining on, or you have Intel C/C++'s 7.x/8x compiler or MS's Visual Studio .NET 2002/2003 with /LTCG specified. With those kinds of caveats, your statement is rather misleading at best. Or, more likely, you've never bothered looking at what code your compiler produces. gcc, in particular, won't inline accessors found in a .cpp file. It won't inline functions until you put -O3 on the commandline or use -finline-functions, neither of which is defaulted. As I noted above, only a few compilers will ever consider inlining any code found in a ..cpp. And considering how slow gcc is without precompiled headers (which might be in the latest versions), then there's a lot of code out there that will never be placed in headers. Quite frankly, if you trust your compiler to produce great code on the 1% of the code where it matters the most, you're an idiot. Compilers do well on 95+% of the code. Automated tests are, imho, the worst way to tell if code should be inlined. There's a combinatorial approach to see which function(s) should be inlined, and which should not be inlined for the most speed. With 20 functions to consider inlining, that's a million (2^20) combinations, each of which must be tested when the *whole* is running. Not a part. Human insight on optimization is how you cut through the billions of real possibilities and find the wins. An automated test might be able to tell you if the compiler produced busted code (again). The 'why did the speed change' part is far more important, and short of inventing Skynet, that's still going to be the realm of humans. Nathan Mates -- <*> Nathan Mates - personal webpage http://www.visi.com/~nathan/ # Programmer at Pandemic Studios -- http://www.pandemicstudios.com/ # NOT speaking for Pandemic Studios. "Care not what the neighbors # think. What are the facts, and to how many decimal places?" -R.A. Heinlein |
|
#5
| |||
| |||
| nokturnal wrote: > Having global variables is faster than having to pass the variable round > from function to function. So, you have time-tested this? and you have compared it to the Singleton pattern with Get() methods? And, you don't mind breaking the style rule that each method only deal with a very few variables? > I use a global array of 3D objects to make my 3D engine run faster; > items in a global array can be referenced as integers (usually) therefore > i can do not have to pass a long pointer into a function specifying the > address of the array in memory - therefore saving on memory management; > some functions may be called a hundred times per frame so every > optimisation counts! Note that is a single entity. A global here and there is mostly harmless. Read-only globals are harmless. The worst of the worst situation is scattered global variables of many types, especially those that affect control flow. -- Phlip http://industrialxp.org/community/bi...UserInterfaces |
|
#6
| |||
| |||
| Nathan Mates wrote: > True only when the accessor exists in a header. And only when you > have inlining on, or you have Intel C/C++'s 7.x/8x compiler or MS's > Visual Studio .NET 2002/2003 with /LTCG specified. .... > gcc, in particular, won't inline accessors found in a .cpp file. .... All of that is about whether inline produces in-line opcodes, not whether it actually makes things faster. It could make them slower. For example, suppose small method Foo() calls small method Bar() twenty times. Now inline Bar(). (Really inline - not just write the keyword.) Foo() got bigger by twenty instances of Bar(). Maybe less, with optimization. But Foo() might now be big enough to overflow the CPU cache. The method thrashes, where before Foo() and Bar() fit right next to each other. So: Time them and see. The C++ thought leaders, such as James Kanze, order their troups to never ever inline unless profiling reveals a real need. -- Phlip |
|
#7
| |||
| |||
| In article <1112676450.491826.18800@g14g2000cwa.googlegroups. com>, phlip2005@gmail.com says... > [...] But Foo() might now be big enough to overflow the CPU > cache. _The_ "CPU cache?" Are you really sure you are not outside your field of expertise here? Your terminology usage indicates you are. > [...] The C++ thought leaders, such as James Kanze, [...] For being one to quickly accuse others of appealing to authority, you do a lot of appealing yourself you know. > > I've always been taught to > > avoid useing globals as much as possible > > Why not post this question a generic programming group, like > news:comp.object, or a group specific to your language? Oh, Philip, please! The OP crossposted to "comp.programming" -- it doesn't get more generic than that. And FYI, "comp.object" is _not_ a generic programming group; the people posting there are into a very particular type of programming methodology. -- Christer Ericson http://realtimecollisiondetection.net/ |
|
#8
| |||
| |||
| Andy White wrote: > I need advice on when to use global and when not. I've always been > taught to avoid useing globals as much as possible but recently > since I've stepped into video game programming, I've heard that > it's ok or "more accepted". I need a guideline for this matter, > thanks. Video games tend not to reuse their own code, unless they are selling the source code engine to some other publisher. So whatever mess you make, tends to matter less. Seriously though, here's the problem with globals/statics -- in a multithreaded environment, if you *write* to them from multiple threads, then they must be properly mutexed or semaphored to avoid a race condition. In general, it makes it hard or impossible to run multiple instances where a global variable retains state even in non-multitasking situations. Look at C's "strtok()" function for a prime example of doing this badly. strtok() hangs onto "state" from call to call (its locally scoped and therefore beyond your direct access, but its static nevertheless), meaning you cannot even perform nested strtok()'s at the same time. So the only globals I would recommend are global functions, and global constants (i.e., variables that are read-only.) Doing so will make your code more "reusable" for other purposes in the future, and will make the code more future proof in general as requirements change for your software development. -- Paul Hsieh http://www.pobox.com/~qed/ http://bstring.sf.net/ |
|
#9
| |||
| |||
| Nathan Mates wrote: > >The second excuse is completely invalid without an automated test to > >time that code and see if it's faster. In C++, if you hide global > >data in a Singleton Pattern object, and if its data members have > >inline Get() methods, then your compiler will produce (generally) > >the same opcodes to access the raw data as if it were naked. > > True only when the accessor exists in a header. ....and the last time you saw Singleton implemented in an implementation file (as opposed to a header) was when? AFAIK, no compilers in use in games today support C++'s export keyword. > With 20 functions to consider inlining, that's a million (2^20) > combinations, each of which must be tested when the *whole* is > running. Not a part. Nobody said 'part'. If you can't generate reproducable metrics, you're reduced to guessing at what might make a difference. Programming by accident is effective given enough time, but minimizing the time only requires writing some scripts and doing some automated builds and test runs that are timed. > Human insight on optimization is how you cut through the billions > of real possibilities and find the wins. Actually, it's fairly well understood that "human insight" when it comes to optimization is generally poor, and that the only true way to know if an optimization strategy works is to time the before and after images. -tom! -- There's really no reason to send a copy of your followup to my email address, so please don't. |
|
#10
| |||
| |||
| nokturnal wrote: > Having global variables is faster than having to pass the > variable round from function to function. I would say if your > going to use them keep use a global_ prefix so as not to get > local and global variables confused. It's best to put data where it belongs logically, for the programmers' sanity. You can code with lots of global variables, and you can code with none. Myself, I prefer the latter because without any global variables (constants don't count, and yet constants are still scoped appropriately) the code is often much easier to understand and you don't have modules reaching over and into one another to get things done. I think that Singleton sucks. I would go so far as to state that Singleton is worse than naked global variables, but mostly because of the fact that people say "singleton" and they mean "global thing that I can change however and whenever I want." It's these global things that you need to worry about... Again, reaching across the world to tweak values is nothing but dangerous. -tom! -- There's really no reason to send a copy of your followup to my email address, so please don't. |
![]() |
| Thread Tools | |
| Display Modes | |
In an effort to better serve ads to our visitors, cookies are used on objectmix.com. For more information, check out our Privacy Policy.