Jump to content

Coding clean and optimizing performance


f13rce
 Share

Recommended Posts

Hey all,

 

After programming for a few years I've noticed that the performance in my projects are low. This is mainly because of bad written code. Since I don't really like to keep that bad habit, I will need a bit of your help and advice. I do know how to code, but the problem is coding for performance. My goal is to improve the performance as much as possible.

I've started coding in Game Maker - where you don't really have classes but objects. I haven't really been learning how to program in performance back then (neither coding clean actually, working with classes etc). So basically I *cough* might *cough* have had a bad start.

 

In my project Ravage Online (the online FPS) I've only have 8 classes - I assume this is low for over 6000 lines of code (also building takes long, etc). Are many classes good to have when looking at performance and are they easy to use?

 

Also, I'm currently programming in MVS2008 in C and C++. Are there any handy tools to record the performance/check your code for performance? Or are there any ways to check the performance using the Leadwerks engine?

 

Then we have the big while loop. I used to put like every bit of code in there with barely any functions (I feel your pain). But writing functions all the time also fills up a lot of space before the int main - should I work with some more classes?

 

I also noticed some people are sketching what they want to code - I would like to try this. Is anyone doing this as well? Does anyone have tips and tricks for that?

 

At last: Do you have any tips, tricks and/or tools about coding clean/optimizing performance? I'm thinking about having a good start with a new project but don't want to end it up like Ravage, where the easiest scenes have a low FPS because of the code.

 

You don't have to answer them all of course - I just need some advice with coding.

 

Big thanks in advance!

 

- Ivar / Evayr

Using Leadwerks Professional Edition (Beta), mainly using C++.

Windows 10 / Linux Mint, Visual Studio 2017. GPU: NVidia GeForce GTX970, CPU: Intel i7 7700K @ 4.20 GHz

Previously known as Evayr.

Link to comment
Share on other sites

The first thing I did was take a look and see if my code was doing anything stupid. For instance, the 0.1 version of Swords and Skellies updates each skeleton including controller, animation, everything, even if it is clear across the map. In the working copy of 0.2, I only update skeletons in a certain radius of the player, and am currently working on animating only if the entity is being drawn.

 

Just the first thing above, though, saved 60 FPS. WOW!

 

There is a profiling library posted on the Asset Store. I have not used it yet. It's marked as broken, but Pixel recently posted that he fixed it.

 

http://www.leadwerks.com/werkspace/files/file/142-profiling-code-for-c/

Link to comment
Share on other sites

Hmm I would say 8 classes is too few for proper OO. It would be pretty difficult locating the problems getting lost in the large classes.

 

You generally want to keep your games in modules (classes) which are easy to manage and have very few public functions such as

  • Initialize Module Function
  • Update Module Function
  • Terminate Module Function

That way the main function code can be kept simple and things within the class can be really easily optimised in manageable chunks.

 

I find it really important to plan out your class structures as it can get really complex if not managed correctly. I often find my classes getting too big and end up re-designing it to have more sub classes. <- at this point I wish I had planned it better.

 

I'll use my GUI System to explain how I do things. I haven't been coding nearly as long as a lot of people here but This is what I have come up with in the short time I've been coding.

 

3 Layers:

- Navigation Layer (Class that manages navigation between Screens and/or games)

- Screen Management Layer (A group of Classes, one for each screen)

- GUI Elements Layer (A group of classes to manage individual GUI Elements such as buttons, sliders. One for each type)

 

So to give you an idea, my current GUI / Navigation system has 14 classes, 10 of which are just for things like buttons. Also all of the Elements are derived classes from a base UIElement class because all elements have some variables and functions that would be the same so It's better to only write it once and use inheritance. (Oh also I haven't even finished writing all the elements or screens)

 

The beauty of it is that once you have written the classes it becomes so easy to use in any number of projects. Each element is an object that you can simply initialize and updates. So for example each UI Element class has the following functions

 

1. Constructor <- Well I use the constructor as the initialize function, taking in all data on position, click box position, scale, images used... etc.

2. int UpateUIElement() This function will update the element. So in the case of a button it will first check if the mouse is hovering and then it will draw the button as either untouched or with a hover glow. Then it checks if the mouse was clicked. If so it returns 1. This update function also calls other private functions within the class but these never get seen once you have written the class.

3. Destructor <- I usually just terminate a UI Element with the class destructor

 

Of course for some elements you need more functions such as choice bars. You need to have a function to add options to the choice bar and such. Just only make public functions when necessary and try keeping it to the minimum Initialize, Update & Terminate function as much as possible. Therefore in your main loop all you call is Update();

 

Main Loop.....s:

Well I don't know how other people do this or if this is even good practice but I never have a single main loop. I have multiple main loops that are responsible for different modules. Going off my example above the Navigation Layer has a While loop with a state machine which checks which screen to activate based on the current state.. Then The code within that screen is called from the navigation layer just once and that screen has its own main loop which only gets terminated when that screen is exited or progressed to another screen. Therefore that while loop can manage everything involved with that particular screen.

 

Now once a particular screen's loop is terminated we go back to the navigation layer which loops around and checks what is the current state based on what was done in the last screen and then it does the same thing as before. Unless the state is 'Exit Game' the navigation layer will call a ManageScreen() function which again will have its own loop.

 

This way I can avoid having a tonne of state checks every single frame which is what you would have if you don't have many classes.

 

Some more examples off the top of my head:

Networking System:

  • Connections Layer -> Send & Receive Layer -> Lag Compensation Layer -> Player Interface Layer (1 class each)

Player System:

  • Base Character Class (This one is to get inherited from)
  • Player Inputs & Movement Layer (Inherits from Base Character Class)
  • Generic Animations Layer
  • Unique Animations Layer
  • Targetting / Player Recognition Layer -> Camera Layer (This one is almost like a sub system

Database System

  • Database Interface / Reader Layer
  • Content Factory (Holds all data on 3D & 2D content Assets)
  • Animation Data Room (Holds all data on animations)
  • Save Game Layer
  • Game Settings Layer
  • Key Bindings Layer

Well... That is a rough as guts way I do it. Its hard to explain in so few words and without pictures. But I find drawing flow graphs of the structure is very important.

 

Also with this method you have to pass class pointers or references through functions. Especially for the database layer because so many other classes need access to it and you only want to make one.

 

Anyway hope this helps. Hope it makes sense. I struggle to explain it without pictures

 

 

 

PS: You did pretty darn well considering you only had 8 classes. Its a lot better than many people on this forum will achieve. wink.png Keep it up. I highly recommend reading the Game Programming Gem's books. They are very very good at explaining these things.

STS - Scarlet Thread Studios

AKA: Engineer Ken

 

Fact: Game Development is hard... very bloody hard.. If you are not prepared to accept that.. Please give up now!

Link to comment
Share on other sites

I made again a test yesterday, and found out that mingw makes 7.4% faster programs than VS2010. Of course that was just one test, but still, speed is everything, and also compiling times are much faster, and also IDE loading times are much faster. VS2008 and VS2010 makes about the same speed programs, but in VS2010 makes it more automatically, while in VS2008 you need to manually optimize the code.

Ryzen 9 RX 6800M ■ 16GB XF8 Windows 11 ■
Ultra ■ LE 2.53DWS 5.6  Reaper ■ C/C++ C# ■ Fortran 2008 ■ Story ■
■ Homepage: https://canardia.com ■

Link to comment
Share on other sites

You need to ascertain where optimisation is important and where it really doesn't matter, that is key. You can waste a lot of time making something faster than has little to no effect on the overall performance.

 

PROFILING is your friend. Profile all your code first and find where the real time is being taken. Then ask yourself for each of the areas where large amounts of time are being consumed, is this expected or do I have an optimisation issue here?

 

This way you will concentrate your effort into the areas which can have an effect. Identifying these areas is half the battle. Optimising those routines sufficiently is the other. Good luck smile.png

 

 

Then we have the big while loop. I used to put like every bit of code in there with barely any functions (I feel your pain). But writing functions all the time also fills up a lot of space before the int main - should I work with some more classes?

There is no need to define your functions before the entry level int main function. You can simply forward declare those functions with a single line per function. What's more, those can be defined in a header file.

 

Good structure and the use of modular code be it Object Oriented or Procedural will help with the readability of the code and also with bug fixing as it promotes encapsulation of functionality but will not in itself increase the performance or efficiency of the code necessarily.

 

Object oriented code lends itself well to most areas of game design and I would strongly recommend it. However, it is often less efficient and should be avoided in some key areas where performance really counts like anything that involves lengthy computations (path finding routines would be a good example where you need to squeeze every last micro second of performance out of your code and the last thing you want to be doing is incurring the overhead of creating thousands of new objects).

Intel Core i5 2.66 GHz, Asus P7P55D, 8Gb DDR3 RAM, GTX460 1Gb DDR5, Windows 7 (x64), LE Editor, GMax, 3DWS, UU3D Pro, Texture Maker Pro, Shader Map Pro. Development language: C/C++

Link to comment
Share on other sites

I tend to lean towards 1 main loop that is about 10 lines or so only. It has the basic LE framework stuff and Flip() and then branches off to the current game state draw and update functions or classes depending on how you do it. The game states would be like "developer.logo", "leadwerks.logo", "main.menu", "gameplay". Each having their own draw and update methods. In C++ I make them their own classes since this breaks things out very nicely and allows for very easy reuse. They would be deriving from some GameState base class so all game states could be stored together in a map with a string key. The game state variable is available for all game state instances so that they can change between each other. As long as I use this same setup for each game I make I simply include the header and source file for the "developer.logo" and "leadwerks.logo" (and any other common gamestate between games) (since those 2 are the same) and it tends to lend to nice reusable code.

 

 

while(!gameQuit)
{
  UpdateFramework();
  gameStates[activeGameState]->Update();
  DrawFramework();
  gameStates[activeGameState]->Draw();
  Flip();
}

 

 

You can also get fancy with transitions and whatnot with this if you like. Some variations would looping through all elements in the gameState map and checking an active, enabled, or visible flag and calling Update() or Draw() on each one to give a layered game state environment.

 

This in itself might give you more than the 8 classes you have and be a nice logical separation.

Link to comment
Share on other sites

If it's appropriate, try not to write to a file in the middle of a game loop. It's about the slowest thing your computer can do (even when using an SSD, but especially when you're not).

 

If you do have to do this, move it off into a new thread, as writing (or reading for that matter) will block the thread that called it until the IO has finished.

 

 

 

Also look for unnecessary code. I had a blonde moment only a few days ago, regarding a loopback server for inter-process communication. When I spotted what I'd done, I commented it appropriately...

 

 

int ConnectToLBS(void)
{
   if(LoopbackServerRunning)
   {
       if(!LoopbackServerClosing)
       {
           //LoopbackServerRunning = true; //well no stuff, of course it's running, that's how we reached this nest... What this line says is: "If it's running, and it's not closing, then it's running" duhhhhh...
           //201203011615 Wait, why was I trying to set that from a connect routine anyway? Double duhhhhh. Answers on a postcard...

LE Version: 2.50 (Eventually)

Link to comment
Share on other sites

Well, I have one important advice for you: writing a future proof code is your biggest enemy!

You would say that I'm wrong, but believe me, programming for games are different than other types of programming.

With some research you'll see that no AAA game is made with a closed source game engine. About %70 of AAA games are made with in-house engines, and the other %30 are made with their own modified versions of commercial engines.

So face the truth: There is NO general code in game development industry. You have to make your own technology for your game.

 

 

Also it is a good practice to write your code in a data-oriented way. This way you have to figure out how your game data is transformed first, then implement some routines to accomplish that transformations.

By data transformation I mean something like this:

User input -> Game Logic -> Physics calculations -> Render engine -> Monitor

 

To achieve this, make a very big flowchart of your game, then design your code specific to the game.

So with every change in the game design, the flowchart needs to be modified.

 

This method has three main advantages:

1- Better performance (because of memory access patterns)

2- Better project scheduling

3- Better readable code

 

For more info, read the publications of DICE and Insomniac, that cover this method in more depth.

 

Object oriented programming is no longer used in game programming, for many reasons that's covered in those documents.

Ali Salehi | Programmer

 

Intel Core i3 2100 @ 3.0GHz | GeForce GTS 450 | 4GB DDR3 RAM | Windows 7 Ultimate x64

LE 2.50 | Visual Studio 2010 | RenderMonkey 1.82 | gDEBugger 5.8 | FX Composer 2.5 | UU3D 3 | xNormal 3.17

 

 

76561198023085627.png

Link to comment
Share on other sites

no AAA game is made with a closed source game engine.

 

There is a large market out there that isn't "AAA" quality. But I do agree that future proofing your code is dangerous and should be used with caution because it can lead to longer development time and for indies that just means more chance of failure. That being said once you get a truely flexible system it can last a long time. Blizzards Lua UI implementation would be a good example of this.

 

 

Object oriented programming is no longer used in game programming

 

I imagine this will spark some conversation.

Link to comment
Share on other sites

Object oriented programming is no longer used in game programming, for many reasons that's covered in those documents.

That does seem an overstatement in my opinion. Sure there is a move towards data oriented design but I know of few engines that don't also use object oriented techniques too. A simple search on available jobs at DICE shows requirements for both object oriented design and data oriented design experience in many of the available jobs!

Intel Core i5 2.66 GHz, Asus P7P55D, 8Gb DDR3 RAM, GTX460 1Gb DDR5, Windows 7 (x64), LE Editor, GMax, 3DWS, UU3D Pro, Texture Maker Pro, Shader Map Pro. Development language: C/C++

Link to comment
Share on other sites

That does seem an overstatement in my opinion. Sure there is a move towards data oriented design but I know of few engines that don't also use object oriented techniques too. A simple search on available jobs at DICE shows requirements for both object oriented design and data oriented design experience in many of the available jobs!

 

I think my statement is misunderstood.

I mean OO is being replaced by DO, and it is no longer the best choice.

Newly developed engines and games are not using it.

Ali Salehi | Programmer

 

Intel Core i3 2100 @ 3.0GHz | GeForce GTS 450 | 4GB DDR3 RAM | Windows 7 Ultimate x64

LE 2.50 | Visual Studio 2010 | RenderMonkey 1.82 | gDEBugger 5.8 | FX Composer 2.5 | UU3D 3 | xNormal 3.17

 

 

76561198023085627.png

Link to comment
Share on other sites

So the word DO is new to me. I found some sites that have a powerpoint presentation around the idea.

 

http://www.slideshar...oriented-design

 

https://docs.google....G5yM3pjZA&hl=en

 

From what I can gather, correct me if I'm wrong, but it's pretty much going back to procedural programming with more focus on how you group your data so that it leads to a number of benefits.

 

 

This article shows a pretty basic example as proves a pretty interesting point.

http://molecularmusings.wordpress.com/2011/11/03/adventures-in-data-oriented-design-part-1-mesh-data-3/

Link to comment
Share on other sites

So the word DO is new to me. I found some sites that have a powerpoint presentation around the idea.

 

http://www.slideshar...oriented-design

 

https://docs.google....G5yM3pjZA&hl=en

 

From what I can gather, correct me if I'm wrong, but it's pretty much going back to procedural programming with more focus on how you group your data so that it leads to a number of benefits.

 

 

This article shows a pretty basic example as proves a pretty interesting point.

http://molecularmusi...-1-mesh-data-3/

The first presentation is the one from DICE that I've mentioned.

 

The article was really nice. It shows the performance benefit in a simple way.

Ali Salehi | Programmer

 

Intel Core i3 2100 @ 3.0GHz | GeForce GTS 450 | 4GB DDR3 RAM | Windows 7 Ultimate x64

LE 2.50 | Visual Studio 2010 | RenderMonkey 1.82 | gDEBugger 5.8 | FX Composer 2.5 | UU3D 3 | xNormal 3.17

 

 

76561198023085627.png

Link to comment
Share on other sites

I'll take a look at these too, thanks for the pointers Lord Hippo. It is something I've been vaguely aware of in the past but never looked at in detail.

Intel Core i5 2.66 GHz, Asus P7P55D, 8Gb DDR3 RAM, GTX460 1Gb DDR5, Windows 7 (x64), LE Editor, GMax, 3DWS, UU3D Pro, Texture Maker Pro, Shader Map Pro. Development language: C/C++

Link to comment
Share on other sites

Oh wow. Thank you all for those detailed responses! I will try some of these out and look more into the information you gave me. This should definitely help me. I'll post some results when I get to that.

 

Many. thanks.

 

Please, feel free to post more if something comes up your mind.

Using Leadwerks Professional Edition (Beta), mainly using C++.

Windows 10 / Linux Mint, Visual Studio 2017. GPU: NVidia GeForce GTX970, CPU: Intel i7 7700K @ 4.20 GHz

Previously known as Evayr.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...