Jump to content

  • Log In with Google      Sign In   
  • Create Account

Misterious (or not) slow performance


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
14 replies to this topic

#1 Juliano Schroeder   Members   -  Reputation: 121

Like
0Likes
Like

Posted 08 December 2011 - 06:05 AM

Hello everyone,

I'm making a little piece of game to learn, so I'm kinda starting everything from scratch just to experience the difficulties. It is very simple by now, but I'm noticing a quick degrading in performance as soon as I start adding more elements to the system.

I have
  • a World object which defines world boundaries and a vector of box objects
  • a Box object that is the main element of the system
  • a PhysicSystem object that handles the boxes movement and collision
  • a Renderer class with static functions to draw the world and the boxes.
Here's the draw function:
void drawFrame() {

        /* ... projection matrix settings .. */
    	
    	physys.calcBoxPositions(); //calculates box movement and detect collision
        
    	Renderer::drawWorld(w);  //draws the world boundaries
    	Renderer::drawWorldBoxes(&w); //draws each box
    	glutSwapBuffers();
}

The box movement is just a constant increment on the y axis. The collision detection each box to all the others and the world, if it detects a collision, it stops incrementing the box position.

void PhysicSystem::calcBoxPositions() {

   std::vector<Box>::iterator it1;
   std::vector<Box> &boxList = this->world.getBoxList();

   for (it1 = boxList.begin(); it1 != boxList.end(); it1++) {
    	Box& b1 = *it1;
    	
    	b1.setXY(b1.getX(), b1.getY() + this->gravity); //gravity is 0.001f

    	bool collided = false;
		std::vector<Box>::iterator it2;

    	for (it2 = boxList.begin(); it2 != boxList.end(); it2++) {

        	Box& b2 = *it2;
        	if (&b1 != &b2) { // not the same box

   				collided = checkCollision(b1,b2);
			if (collided) {
				b1.stop();
				collided = false;
			}
		}
   

    	if (b1.bottom() <= this->world.getY())
 			collided = true;

        if (b1.top() >= this->world.getY() + this->world.getHeight())
 			collided = true;

        if (collided) {
 			b1.stop();
 			collided = false;
    	}	
  }
}

I start the thing with 4 boxes and it runs smoothly. When I add like 5 more boxes the frame rate drops heavily. I know that the collision checking has square complexity, but I don't think that it alone is the problem with so few boxes.

Any council/help/suggestion/critic will be appreciated,
Thanks
http://www.creationguts.com - The Guts of Creation
drawing, programming and game design.

Sponsor:

#2 Álvaro   Crossbones+   -  Reputation: 13907

Like
0Likes
Like

Posted 08 December 2011 - 06:17 AM

Use a profiler to identify where your program is spending its time.

#3 way2lazy2care   Members   -  Reputation: 782

Like
1Likes
Like

Posted 08 December 2011 - 10:32 AM

Your blocks are nested wrong. You are checking against world collision N^2 times instead of N times. That's probably not it, but it's definitely a problem.

void PhysicSystem::calcBoxPositions() 
{

	std::vector<Box>::iterator it1;
	std::vector<Box> &boxList = this->world.getBoxList();

	for (it1 = boxList.begin(); it1 != boxList.end(); it1++) 
	{
		Box& b1 = *it1;
		
		b1.setXY(b1.getX(), b1.getY() + this->gravity); //gravity is 0.001f

		bool collided = false;
		std::vector<Box>::iterator it2;

		for (it2 = boxList.begin(); it2 != boxList.end() && !collided; it2++) {

			Box& b2 = *it2;
			if (&b1 != &b2) 
			{ // not the same box
				collided = checkCollision(b1,b2);
			}
		}


		if (b1.bottom() <= this->world.getY())
		{
			collided = true;
		}
    	else if (b1.top() >= this->world.getY() + this->world.getHeight())
		{
			collided = true;
		}

		if (collided)
		{
			b1.stop();
			collided = false;
		}   	
	}
}

A couple things that I'd fix about your code that would involve more rewrites would be the following. Move your movement logic (b1.setXY(b1.getX(), b1.getY() + this->gravity); //gravity is 0.001f) to be completely separate from your collision logic. It will make it less confusing on the whole. Second, I would use Allman style indents (http://en.wikipedia.org/wiki/Indent_style). They are much easier to visually parse.

#4 Juliano Schroeder   Members   -  Reputation: 121

Like
0Likes
Like

Posted 08 December 2011 - 10:45 AM

@alvaro: thanks, I'm gonna try some profiler in the future.

@way2lazy2care: yes, i realized they were nested wrong, I think it was when i copied the code to post, It didn't indent well and I removed some comments and code not related to the issue. Or maybe It was a mistake, need to check later.

I could put the internal for loop inside the checkCollision function and pass only one Box to it. Then the outer for loop move the Box and calls checkCollision(b1); and after calls a checkWorldCollision(b1);

Still, no idea why I'm having such a slow performance..
http://www.creationguts.com - The Guts of Creation
drawing, programming and game design.

#5 Tournicoti   Prime Members   -  Reputation: 684

Like
0Likes
Like

Posted 08 December 2011 - 10:55 AM

Hello
How much do the performances fall ? I had a problem a bit like this, where performances drop to half suddenly when adding another entity, it came from the fact that I activated VSync. (wasn't able to have 60Hz frame rate, so it drops directly to 30 Hz due to vSync)
Do you enable VSync ?

#6 Juliano Schroeder   Members   -  Reputation: 121

Like
0Likes
Like

Posted 08 December 2011 - 11:03 AM

Hmm, I'm not sure. How can I enable/disable VSync?
http://www.creationguts.com - The Guts of Creation
drawing, programming and game design.

#7 Tournicoti   Prime Members   -  Reputation: 684

Like
0Likes
Like

Posted 08 December 2011 - 11:07 AM

Hmm, I'm not sure. How can I enable/disable VSync?


This is done when calling IDXGISwapChain::Present() (I talk about DX10 but there must be a similar way for other dx versions)

For example :

	if (vSync)
		g_pSwapChain->Present(1,0);// VSync
	else
		g_pSwapChain->Present(0,0); // presents the frame immediately


#8 Juliano Schroeder   Members   -  Reputation: 121

Like
0Likes
Like

Posted 08 December 2011 - 11:30 AM

I'm actually using OpenGL, gonna check how it is done there. Thanks.
http://www.creationguts.com - The Guts of Creation
drawing, programming and game design.

#9 way2lazy2care   Members   -  Reputation: 782

Like
0Likes
Like

Posted 08 December 2011 - 11:51 AM

@way2lazy2care: yes, i realized they were nested wrong, I think it was when i copied the code to post, It didn't indent well and I removed some comments and code not related to the issue. Or maybe It was a mistake, need to check later.


hum. Where do you call your calcBoxPositions? Maybe it's just getting called too frequently. If you comment out where you call it and the framerate jumps back up it would be kind of a way to isolate it to that function.

edit: If commenting out that line and turning off vertical sync both fix the issue independently (ie turning either one off but not both), then I'd suggest spinning your drawing code off away from your game logic so it can go run on it's own without having to wait for the physics stuff.

That said I don't feel like it's vsync, but that's more my gut than any reasonable explanation.

#10 Juliano Schroeder   Members   -  Reputation: 121

Like
0Likes
Like

Posted 08 December 2011 - 12:12 PM

Well, if I comment out nothing happens hehe, so the framerate will probably go up. I call the function in my drawFrame function. It gets called every time a frame is drawn and I don't make any framerate control to set a specific FPS. It goes on its own accord.
http://www.creationguts.com - The Guts of Creation
drawing, programming and game design.

#11 way2lazy2care   Members   -  Reputation: 782

Like
0Likes
Like

Posted 08 December 2011 - 12:24 PM

Well, if I comment out nothing happens hehe, so the framerate will probably go up.

Unless the problem isn't in that function :-p

I call the function in my drawFrame function. It gets called every time a frame is drawn and I don't make any framerate control to set a specific FPS. It goes on its own accord.


Put it in your game loop. Your physics shouldn't depend on your graphics at all so keep them as separated as possible. That's more than likely what the problem is at the core.

#12 rip-off   Moderators   -  Reputation: 8726

Like
0Likes
Like

Posted 08 December 2011 - 12:31 PM

You can improve this naive collision loop by having the inner loop move from it1 + 1 to end, rather than comparing every single object against every single other object. To make this work you would need to notify both objects of a collision when it occurs in the inner loop.

You could also decide to test the world first and skip the test against other objects (assuming that world collision is the most frequent type of collision), depending on what "stop()" does.

#13 Juliano Schroeder   Members   -  Reputation: 121

Like
0Likes
Like

Posted 08 December 2011 - 12:42 PM

I'm using glut and i put everything on my drawFrame callback with glutDisplayFunc(). The other callback i can set is through glutIdleFunc() but I don't know if it would be consistent to put my physics in the Idle callback and the rendering in the drawing callback.

I think it could be said that my game loop for now is the drawFrame function. Don't know exactly how I can improve it.

Another note: the physicsystem doesn't depend on the graphics it is just called before the graphics are drawn.
http://www.creationguts.com - The Guts of Creation
drawing, programming and game design.

#14 Juliano Schroeder   Members   -  Reputation: 121

Like
0Likes
Like

Posted 08 December 2011 - 12:47 PM

You can improve this naive collision loop by having the inner loop move from it1 + 1 to end, rather than comparing every single object against every single other object. To make this work you would need to notify both objects of a collision when it occurs in the inner loop.

You could also decide to test the world first and skip the test against other objects (assuming that world collision is the most frequent type of collision), depending on what "stop()" does.


Good idea. I would need to put a collided attribute in the Box object to notify both of them. As for now the boxes only fall and collide to each other and to the bottom of the world. Stop() only sets the Box::direction attribute to 0.

The code that moves the box is actually like this ( I omitted direction to make it clearer):
 b1.setXY(b1.getX(), b1.getY() + b1.getDirection() * this->gravity); //gravity is 0.001f

Box::direction defaults to -1 and stop() sets it to 0.
http://www.creationguts.com - The Guts of Creation
drawing, programming and game design.

#15 Vortez   Crossbones+   -  Reputation: 2704

Like
0Likes
Like

Posted 08 December 2011 - 01:19 PM

For vsync in opengl, try this:


// OpenGL VSync Extension
typedef BOOL (APIENTRY *PFNWGLSWAPINTERVALFARPROC)(int);

PFNWGLSWAPINTERVALFARPROC wglSwapIntervalEXT;

void SetVSync(int i){
if(wglSwapIntervalEXT)
wglSwapIntervalEXT(i);
}




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS