13 Optimization Tips for Game Devers

Whether you're a newbie or an experienced programmer, any questions, help, or just talk of any language will be welcomed here.

Moderator: Coders of Rage

Post Reply
User avatar
Arce
Jealous Self-Righteous Prick
Jealous Self-Righteous Prick
Posts: 2153
Joined: Mon Jul 10, 2006 9:29 pm

13 Optimization Tips for Game Devers

Post by Arce »

[ebook] (Computer Graphics) Game programming book C wrote:1) Don’t be afraid to use global variables. Many video games don’t use
parameters for a lot of time-critical functions, instead using a global
parameter passing area. For example, if a function looks like this:
void Plot(int x, int y, int color)
{
// plots a pixel on the screen
video_buffer[x + y*MEMORY_PITCH] = color;
} // end Plot
The body of the function takes less time than the function call. This is
due to the parameter pushing and popping on the stack. In this case a
better method might be to create a global parameter passing area and
then make assignments before a call, like this:
int gx,gy,gz,gcolor; // define some globals
void Plot_G(void)
{
// plot a pixel using globals
video_buffer[gx + gy*MEMORY_PITCH] = gcolor;
} // end Plot_G

2) Use inline functions. You can improve the previous trick even more by
using the inline directive to get rid of the function call completely. The
inline directive instructs the compiler to make its best attempt to put
the code for the function right where it’s called, rather than making the
actual function call. Of course, this makes bigger programs, but speed is
more important. Here’s an example:
inline void Plot_I(int x, int y, int color)
{
// plots a pixel on the screen
video_buffer[x + y*MEMORY_PITCH] = color;
} // end Plot_I
Notice that I didn’t use globals because the compiler will in effect perform
the same type of data aliasing. However, globals would come in
handy if only one or two of the parameters were changing between
calls because the old values could be used without reloading.

3) Always use 32-bit variables rather than 8- or 16-bit. The Pentium and
later processors are totally 32-bit. This means that they don’t like 8- or
16-bit data words, and in fact, smaller data can slow them down
due to caching and other related memory addressing anomalies. For
example, you might create a structure that looks something like this:

struct CPOINT
{
short x,y;
unsigned char c;
} // end CPOINT
Although this may seem like a good idea, it’s not! First, the structure
itself is now five bytes long—(2*sizeof(short) + sizeof(char))
=5. This is really bad, and it’s going to wreak havoc on the memory
addressing. A better approach is the following structure:
struct CPOINT
{
int x,y;
int c;
} // end CPOINT

This new structure is much better. For one thing, all the elements are the same size—
that is, sizeof(int) = 4 bytes. Therefore, a single pointer can be incremented on a
DWORD boundary to access any member. Of course, the new structure is now
(3*sizeof(int)) = 12 bytes, but at least it’s a multiple of 4 or on a DWORD boundary.
This is definitely going to improve performance.
In fact, if you really want to make things rock, you can pad all structures to make
them multiples of 32 bytes. This is the optimal length due to standard on-chip cache
line sizes in the Pentium class processors. You can pad manually by adding dummy
variables, or you can use a compiler directive (the easy way). Of course, this may
waste a lot of memory, but it may be worth it for the increase in speed.

4) Comment the heck out of your code. Game programmers are notorious
for not commenting their code. Don’t make the same mistake. Clean,
well-commented code is always worth the extra typing.

5) Program in a RISC-like (Reduced Instruction Set Computer) manner. In
other words, make your code simple rather than complex. Pentium and
Pentium II processors in particular like simple instructions rather than
complex ones. And making your code longer, with simpler instructions,
makes it easier for the compiler. For example, don’t do this:
if ((x+=(2*buffer[index++])>10)
{
// do work
} // end if
Do this:
x+=(2*buffer[index]);
index++;
if (x > 10)
{
// do work
} // end if
There are two reasons for coding like this. First, it allows a debugger to
put break points between code sections. Second, it makes it easier for
the compiler to send simplified code to the Pentium, which allows it to
process more code in parallel using multiple execution units. Complex
code is bad!

6) Use binary shifts for simple multiplication of integers by powers of 2.
Since all data in a computer is stored in binary form, shifting the bit pattern
to the left or right is equivalent to multiplication or division,
respectively. For example:
int y_pos = 10;
// multiply y_pos by 64
y_pos = (y_pos <<6>> 3); // 1/2^3 = 1/8
You’ll see more tricks like this when you get to the optimization
chapters. Cool, huh?

7) Write efficient algorithms. All the assembly language in the world isn’t
going to make an n^2 algorithm go faster. It’s better to use clean,
efficient algorithms rather than brute force.

8) Don’t optimize your code as you program. This is usually a waste of
time. Before you start heavy optimization, wait until you’re done with a
major code block or until you’re done with the whole game. This will
save you time in the end because you won’t have to deal with cryptic
code or optimizations that aren’t necessary. When the game is done,
that’s when you should start profiling and finding problem areas to
optimize. On the other hand, don’t program sloppily.

9) Don’t write a lot of complex data structures for simple objects. Just
because linked lists are cool doesn’t mean you should use them
for a fixed array that you know will always be around 256 items. Just
allocate it statically and be done with it. Video game programming is
90 percent data manipulation. Keep your data as simple and visible as
possible so you can access it quickly, do what you need to, and move on.
Make sure the data structure fits the problem.

10) Use C++ sparingly. If you’re a seasoned professional, go ahead and do as
you please, but don’t go class crazy or overload everything to death. In
the end, simple, straightforward code is the best and easiest to debug.
And I never want to see multiple inheritance!

11) If you see that you’re going down a rocky road, stop, back up, and take
a detour. I have seen many game programmers start down a bad programming
line and bury themselves. It’s better to realize you made a
mistake and redo 500 lines of code than to have a generally undesirable
code structure. So, if you see a problem with what you’re doing, reevaluate
it and make sure that the time you’re saving is
worth it.

12) Back up your work regularly. When you’re writing game code, you’re
going to lock up the system fairly frequently. Redoing a sorting algorithm
is one thing, but redoing the AI for a character and the collision
detection is another.

13) Before you start on your game projects, be organized. Use reasonable
filenames and directory names, come up with a consistent variable naming
convention, and try to use separate directories for graphics and
sound data rather than dumping everything in one directory.
User avatar
Falco Girgis
Elysian Shadows Team
Elysian Shadows Team
Posts: 10294
Joined: Thu May 20, 2004 2:04 pm
Current Project: Elysian Shadows
Favorite Gaming Platforms: Dreamcast, SNES, NES
Programming Language of Choice: C/++
Location: Studio Vorbis, AL
Contact:

Post by Falco Girgis »

I like the "don't go crazy with C++" one.
User avatar
MarauderIIC
Respected Programmer
Respected Programmer
Posts: 3406
Joined: Sat Jul 10, 2004 3:05 pm
Location: Maryland, USA

Post by MarauderIIC »

(more necromancy!) Guess we should keep those in mind.
I realized the moment I fell into the fissure that the book would not be destroyed as I had planned.
User avatar
dejai
Chaos Rift Junior
Chaos Rift Junior
Posts: 207
Joined: Fri Apr 11, 2008 8:44 pm

Post by dejai »

So to sum it up don't abstract to the nth degree :D
kilgariff
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 17
Joined: Wed May 07, 2008 8:45 pm
Current Project: ArkEngine, Regalia
Favorite Gaming Platforms: PC (Linux, Windows)
Programming Language of Choice: C++ and Assembly
Location: Scotland
Contact:

Post by kilgariff »

Multiple inheritance?
Like.. inheriting from an object that inherits from an object?

I didn't think there was anything wrong with that.

Like for example, in my last engine's dynamic component architecture, I had a base component class, a component interface, and a component implementation ( which resides in an SO ( DLL for you winpeople ) ).

This is useful because I have a kind of abstraction object ( plugin manager? ) that needs to access all types of components, and therefore, can use the base component class.

I mean, I know going crazy as in 5 or 6 levels of inheritance is both bad practice and very mid-90s, but don't be afraid to exploit a useful feature :)

Also, it's good to see that this guy talks about development time optimization as well as actual code optimization.
Carmack: "The most important thing is to try and learn things deeply. Don't try for a superficial knowledge of a lot of things. I've gotten where I am from knowing everything deeply, down to the lowest level."
Thanatos454
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 7
Joined: Tue May 27, 2008 12:03 pm
Location: Indiana

Post by Thanatos454 »

kilgariff wrote:Multiple inheritance?
Like.. inheriting from an object that inherits from an object?

I didn't think there was anything wrong with that.

Like for example, in my last engine's dynamic component architecture, I had a base component class, a component interface, and a component implementation ( which resides in an SO ( DLL for you winpeople ) ).

This is useful because I have a kind of abstraction object ( plugin manager? ) that needs to access all types of components, and therefore, can use the base component class.

I mean, I know going crazy as in 5 or 6 levels of inheritance is both bad practice and very mid-90s, but don't be afraid to exploit a useful feature :)

Also, it's good to see that this guy talks about development time optimization as well as actual code optimization.

Multiple inheritance is when you have a derived class inherited from multiple classes.

Code: Select all

class CFoo: public CBaseFoo, public CBaseBar
{
       /................/
};
Really I have never used it.[/code]
Post Reply