TGB Crowd Test 3 & 4
by Brian Wilson · 12/04/2008 (6:37 pm) · 6 comments
So I needed a break from my other projects and decided to finally knock out my next installment of my crowd generator. There were two specific things I wanted to do: The first was to remove one layer of my runner object by combining the skin layer and the outline of the skin into one imagemap (duh). Considering each runner in the test consisted of 2-5 layers/objects (depending on randiness of course), it made sense to combine the 2 "always-on" layers/objects into one. That was the only change in Crowd Test 3, so no need to really publish a blog about it, it was only about 10 minutes worth of work in a photo editor and some block qoutes to kill the extra object. But that little change lead to an obvious performance increase (see graphs below). However, it didn't test the true performance bottleneck: Object creation/destruction. For that, I went and founded my re-engineering based on Stephen Zepp's recommendation from my Crowd Test 2 blog: To load the objects into a SimSet, then instead of deleting each object at the end of the run, I simply move them back to start to run again.
See the change for yourself:
You'll notice the object handling bottleneck show up at 0:32 and 0:41 as I increase the saturation in two steps. 0:32 is an increase from 6546 objects to 8183 objects, and 0:41 is a further increase to 10228 objects. You'll notice that once the object creation is completed, the FPS stables and runs consitant at the given saturation level.
Arbitrary Screenshot!

And now for the data!
Crowd001 - The first and 2nd versions of the Crowd Test use the same object handling code, so both versions are represented here.
Crowd003 - Crowd Test 3 was just a reduction in layers in the runner, reducing each runner by 1 object.
Crowd004 - Crowd Test 4 contains the new object handling code that moves runners back to start rather than destruction and recreation.
A table showing the revisions:

And now some chart fun:





Psuedocode showing change in object creation:
New code for handling world limit:
Code to call the generator
See the change for yourself:
You'll notice the object handling bottleneck show up at 0:32 and 0:41 as I increase the saturation in two steps. 0:32 is an increase from 6546 objects to 8183 objects, and 0:41 is a further increase to 10228 objects. You'll notice that once the object creation is completed, the FPS stables and runs consitant at the given saturation level.
Arbitrary Screenshot!

And now for the data!
Crowd001 - The first and 2nd versions of the Crowd Test use the same object handling code, so both versions are represented here.
Crowd003 - Crowd Test 3 was just a reduction in layers in the runner, reducing each runner by 1 object.
Crowd004 - Crowd Test 4 contains the new object handling code that moves runners back to start rather than destruction and recreation.
A table showing the revisions:

And now some chart fun:





Psuedocode showing change in object creation:
function newRunner()
{
%runner = new t2dAnimatedSprite()
{
...object code...
Worldlimit is set to NULL // changed from KILL
%runner.runSpeed=... // stores objects randomly generated speed for later use:
$runnerSimSet.add(%this); // first of 2 SimSets, this one is for tracking
// actual runner count
}
... // the other objects are created
// just like Crowd Test 2, with
// the base and skin object combined
// to 1 and each object had some vars
// removed as well.
}New code for handling world limit:
function runnerClass::onWorldLimit(%this)
{
$runnerFinishedSimSet.add(%this);
// $saturationArray is an array of graded runner saturations
// $runnerSaturation is an arbirary value from 1(conjested)-10(light)
// if more runners are out than governed by the current saturation
// setting, then delete them
if($runnerSimSet.getCount()>$saturationArray[$runnerSaturation])
%this.safeDelete();
else
{
%this.setPositionX("-70") //reset to start
%this.setLinearVelocityX(%this.runSpeed); // make sure he runs at orig speed
}
}Code to call the generator
function levelLoop()
{
if($runnerSimSet.getCount()<$saturationArray[$runnerSaturation])
newRunner(); // if there aren't enough object to satisfy
// the saturation requirement, then make them
$runnerCounter = getRandom($runnerSaturation,$runnerSaturation*5);
schedule($runnerCounter,0, "levelLoop");
}
#2
The algo was intended to give a sloping effect to spread the runners out. I can basically put a minimum value on the schedule() for creating a runner and that should fix it. This should allow for smooth saturation tweeking in the creation end. I will also have to come up with another method for deletion as onWorldLimit() would have a lot of triggers when the saturation is reduced and objects are set up to delete. What I can do is write a deletion queue and put the same minimum schedule() timer on the deletion cycle.
Of course a static schedule() min won't be good enough to make it a portable test, as I would be making based on performance on my system. So what I can do is add a modifier to it based on my performance metric:
I think any performance tweeks beyond that will have to come from source modification, and I'm not sure that's in the original scope of this idea, which was to see how many objects TGB could handle out-of-the-box. One of the thing about tests like these on other engines, the ogre3d demos come to mind, is that I don't feel they are valid tests, as they are engine modifications to perform a single task, with much of the core engine features missing in order to achieve high numbers. Personally I like to see what the engine can do in it's default state.
But fear not, I have a few interesting plans for Crowd Test 5 (aka: the "Avoid the Real Project" project)... ;p
12/04/2008 (11:55 pm)
I think the only thing left that I can do to improve performance with script is to throttle the creation rate at high saturation rates. The throttling algorythm was created when I was only trying to get 500-600 runners on screen, so when I turn the saturation is all the way, there's no process really in place to keep the engine from trying to create a rediculous number of objects in a ludicrously short period of time. The algo was intended to give a sloping effect to spread the runners out. I can basically put a minimum value on the schedule() for creating a runner and that should fix it. This should allow for smooth saturation tweeking in the creation end. I will also have to come up with another method for deletion as onWorldLimit() would have a lot of triggers when the saturation is reduced and objects are set up to delete. What I can do is write a deletion queue and put the same minimum schedule() timer on the deletion cycle.
Of course a static schedule() min won't be good enough to make it a portable test, as I would be making based on performance on my system. So what I can do is add a modifier to it based on my performance metric:
$rc = runner count; $fps = Frames per Second; $rpf = $rc/$fps; //Runners per Frame; $perfomance = $fps/$rpf;
I think any performance tweeks beyond that will have to come from source modification, and I'm not sure that's in the original scope of this idea, which was to see how many objects TGB could handle out-of-the-box. One of the thing about tests like these on other engines, the ogre3d demos come to mind, is that I don't feel they are valid tests, as they are engine modifications to perform a single task, with much of the core engine features missing in order to achieve high numbers. Personally I like to see what the engine can do in it's default state.
But fear not, I have a few interesting plans for Crowd Test 5 (aka: the "Avoid the Real Project" project)... ;p
#3
12/05/2008 (10:14 am)
You have been busy, both with the crowd runs, and that wheel "proof of concept" you have on your vimeo site. Maybe you could find a way to combine them both? ^_^
#4
12/05/2008 (10:56 am)
That is really cool, and the data is very interesting.. Thanks for posting, Brian!
#5
12/05/2008 (2:07 pm)
Sweet dude. I'm definitely picturing two armies colliding and the ensuing carnage.
#6
12/07/2008 (10:41 am)
I tried to do the same thing using Torque X, and after 79 sprites they started to disappear! Has someone tried that before? This is killing my game... 
Employee Michael Perry
ZombieShortbus
Great follow up .plan. Very good data and analysis =)