program grinding to a halt....

Started by
8 comments, last by Keebler 16 years, 2 months ago
This code block seems to get slower and slower... The particle count is almost the same but the time the block took to run has increased massivly...(Emitter count is at 1 this whole time)

Time: 8267	  Particle Count: 158
Time: 6433	  Particle Count: 158
Time: 3245	  Particle Count: 160
Time: 4901	  Particle Count: 161
Time: 4994	  Particle Count: 162
Time: 6719	  Particle Count: 162
Time: 5007	  Particle Count: 163
Time: 6643	  Particle Count: 163
Time: 5055	  Particle Count: 164
Time: 6689	  Particle Count: 164
Time: 9049	  Particle Count: 163
Time: 3054	  Particle Count: 165
Time: 5491	  Particle Count: 167
Time: 5110	  Particle Count: 168
Time: 7179	  Particle Count: 168
Time: 2978	  Particle Count: 170
Time: 7143	  Particle Count: 170
Time: 6925	  Particle Count: 170
Time: 5325	  Particle Count: 171
Time: 9280	  Particle Count: 170
Time: 9105	  Particle Count: 169
Time: 11169	  Particle Count: 167
Time: 7453	  Particle Count: 167

Time: 255117	  Particle Count: 161
Time: 266118	  Particle Count: 160
Time: 72346	  Particle Count: 162
Time: 64797	  Particle Count: 164
Time: 132198	  Particle Count: 165
Time: 130426	  Particle Count: 166
Time: 258557	  Particle Count: 165
Time: 276580	  Particle Count: 164
Time: 324695	  Particle Count: 162
Time: 262078	  Particle Count: 161
Time: 132970	  Particle Count: 162
Time: 194183	  Particle Count: 162
Time: 129831	  Particle Count: 163
Time: 130800	  Particle Count: 164
Time: 261817	  Particle Count: 163
Time: 139235	  Particle Count: 164
Time: 333496	  Particle Count: 162
Time: 133433	  Particle Count: 163
Time: 256135	  Particle Count: 162
Time: 198325	  Particle Count: 162
Time: 126966	  Particle Count: 163
Time: 190183	  Particle Count: 163
The offending block:

void c_system::update()
{
	LARGE_INTEGER counter1, counter2;
	QueryPerformanceCounter(&counter1);
	for(std::vector<c_emitter*>::iterator it = emitter_list.begin(); it != emitter_list.end(); it++)
	{
		if((*it) == NULL) continue;
		(*it)->update();
	}
	for(std::vector<c_part*>::iterator it = part_list.begin(); it != part_list.end(); it++)
	{
		if((*it) == NULL) continue;
		(*it)->update();
	}
	QueryPerformanceCounter(&counter2);
	cgm::log<< "Time: " << counter2.QuadPart - counter1.QuadPart << "\t  Particle Count: " << count_part << "\n";
}


The particles are of type "class c_part_point : public c_part" c_part_point::update()

void c_part_point::update()
{
	
	age++;
	speed += speed_change;
	direction += direction_change;
	x += lengthdir_x(speed, direction);
	y += lengthdir_y(speed, direction);
	if (life != -1 && age == life)
	{
		delete this;
		return;
	}

	if(colour_fade) colour_fade_calc();
	
}


c_part::~c_part() -(c_part_point doesn't have it's own deconstructure)

c_part::~c_part()
{
        for (std::vector<c_part*>::iterator it = owner_sys->part_list.begin(); it != owner_sys->part_list.end(); it++)
	{	
		if ((*it)==this)
		{
			owner_sys->part_list.erase(it);
			break;
		}
	}
	count_part--;
}


Why would this get slower and slower? The entire code block (includeing the delete parts) are running from within the 1st 3 seconds yet it keeps slowing down untill it virtualy stops (takes about 15 min for it to get that bad)...
Advertisement
Why use a separate particle counter from part_list::size()? Are you sure that your count is actually synchronized with the actual size of the vector?
Also, it would seem that you're deleting the instance from the list within the middle of iterating the list:

loop{    delete particle         remove self from list}


I'm pretty sure that a vector's iterator can be invalidated by modifications to the list if a memory allocation is required.

it's far better to just flag for deletion and running separate remove_if call

I don't know if that's related to your performance problem, but i think it's definitely a horrible bug in your code.

-me
I tested with both they get the same result. I suppose there I should really use the size() there.

The reason it exists is it's a global and tracks the total particle count in the entire game (as each particle system thats created gets it's own vector for storing particles). Here I only have 1 system for testing though so the values are the same.
I doubt it will make much of a difference but ++it cam be faster than it++. it++ can make a copy of it every time it is called.
if I do:
	for(std::vector<c_part*>::iterator it = part_list.begin(); it != part_list.end(); ++it)


It crashes here:
<vector>
	_Myt& operator++()		{	// preincrement		_SCL_SECURE_VALIDATE(this->_Has_container());//HERE LINE 116		_SCL_SECURE_VALIDATE_RANGE(_Myptr < ((_Myvec *)(this->_Getmycont()))->_Mylast);


I'm not sure why. At worst it should skip the 1st or last value value the conditional still applies regardless of if it is increased before or after the code block...
A loop that switches from i++ to ++i should be functionally equivalent. If that one change caused the crash I suspect you may be overwriting memory somewhere.

C++: A Dialog | C++0x Features: Part1 (lambdas, auto, static_assert) , Part 2 (rvalue references) , Part 3 (decltype) | Write Games | Fix Your Timestep!

ok what would be a good way to remove elements that have been deleted from the vector?
Quote:
http://www.cppreference.com/cppvector/erase.html

The erase() function ... deletes the element at location loc ... The return value is the element after the last element erased.


if((*it) == NULL) continue;(*it)->update();if((*it)->shouldRemove()) it = emitter_list.erase(it);
“Always programm as if the person who will be maintaining your program is a violent psychopath that knows where you live”
You really don't want to be doing that much dynamic allocation / destruction.

One way to speed it up would be to use a pool of particles and just tag them as free after their lifetime is over. So basically, you come up with a max number of particles for the system and you allocate that number of particles ahead of time (or reserve if you're using STL), then you tag all of them as available by setting age less than zero or adding a bool (bInUse), etc.

Then, as the system wants to create particles it just uses the "free pool" of particles instead of actually new'ing them.

I would just point you to my open-source particle system Particle Chamber here on GameDev.net, but the link is broken. (Update below)

If you want the source, just email me at richbenson <@> gmail <.> com and I'll send you the .zip.

Update: The GameDev link is back up.
This is the link to the Special Effects page:
http://www.gamedev.net/reference/list.asp?categoryid=72

If you scroll down to Subcategory: Particle Systems, you'll see Particle Chamber a few entries down.

[Edited by - Keebler on April 5, 2008 10:50:01 AM]

This topic is closed to new replies.

Advertisement