I need help with making this bit of code faster:
UnitBase* Formation::operator[](ushort offset)
{
UnitBase* unit = 0;
if (offset < itsNumFightingUnits)
{
ushort j = 0;
for (ushort i = 0; i < itsNumUnits; ++i)
{
if (unitSetup[i] == UNIT_ON_FRONT)
{
if (j == offset)
unit = unitFormation[i];
++j;
}
}
}
else
throw NotFound();
return unit;
}
So, to give some background, I have this class Formation which contains an array of pointers to UnitBase objects, called UnitFormation. The UnitBase* array has an equally sized array of numbers that indicate the status of each corresponding UnitBase object, called UnitSetup.
I have overloaded the [] operator so as to return only pointers to those UnitBase objects that have a certain status, so if I ask for itsFormation[5], the function does not necessarily return UnitFormation[5], but the 5th element of UnitFormation that has the status UNIT_ON_FRONT.
I have tried using the code above, but according to my profiler, it is taking way too much time. Which makes sense, since the algorithm has to count all the elements before returning the requested pointer.
Do I need to rethink the whole problem completely, or can this be made somehow faster?
Thanks in advance.
I have redesigned the solution completely, using two vectors, one for units on the front, and one for other units, and changed all algorithms such that a unit with a changed status is immediately moved from one vector to another. Thus I eliminated the counting in the [] operator which was the main bottleneck.
Before using the profiler I was getting computation times of around 5500 to 7000 ms. After looking at the answers here,
1) I changed the loop variables from ushort to int or uint, which reduced duration by ~10%,
2) I did another modification in a secondary algorithm to reduce the duration by a further 30% or so,
3) I implemented the two vectors as explained above. This helped reduce the computation time from ~3300 ms to ~700 ms, another 40%!
In all that’s a reduction of 85 – 90%! Thanks to SO and the profiler.
Next I’m going to implement a mediator pattern and only call the updating function when required, perhaps oozing out a few more ms. 🙂
New code that corresponds to the old snippet (the functionality is completely different now):
Much shorter and more to the point. Of course, there were many other heavy modifications, most important being that unitFormation is now a
std::vector<UnitFormationElement*>rather than simply aUnitBase**. TheUnitFormationElement*contains theUnitBase*along with some other vital data that was hanging around in theFormationclass before.