Reduce amount of calls to common functions
Example function: https://gitlab.com/OpenMW/openmw/-/blob/593a16737c5b8e6767f56aa160815747c8020d2f/apps/openmw/mwclass/creature.cpp#L813-850
There are:
- 3 calls to
ptr.getCellRef()
- 5 calls to
ptr.getRefData()
- 6 calls to
MWBase::Environment::get().getWorld()
Things like this play heavily into optimizations, the compiler is not capable of reducing the calls down to a single one as they may have side effects.
As we all know branchless code is faster code, plus it probably makes the code slightly cleaner if we have the necessary variables setup at the function start or somewhere close, that relies heavily on the context.
Here is an example of what the refactored function could look like:
void Creature::respawn(const MWWorld::Ptr& ptr) const
{
const MWMechanics::CreatureStats& creatureStats = getCreatureStats(ptr);
auto& refData = ptr.getRefData();
if (refData.getCount() > 0 && !creatureStats.isDead())
return;
if (!creatureStats.isDeathAnimationFinished())
return;
const auto& world = MWBase::Environment::get().getWorld();
const MWWorld::Store<ESM::GameSetting>& gmst = world->getStore().get<ESM::GameSetting>();
static const float fCorpseRespawnDelay = gmst.find("fCorpseRespawnDelay")->mValue.getFloat();
static const float fCorpseClearDelay = gmst.find("fCorpseClearDelay")->mValue.getFloat();
float delay = refData.getCount() == 0 ? fCorpseClearDelay : std::min(fCorpseRespawnDelay, fCorpseClearDelay);
if (isFlagBitSet(ptr, ESM::Creature::Respawn)
&& creatureStats.getTimeOfDeath() + delay <= world->getTimeStamp())
{
if (auto& cellRef = ptr.getCellRef(); cellRef.hasContentFile())
{
if (refData.getCount() == 0)
{
refData.setCount(1);
const std::string& script = getScript(ptr);
if (!script.empty())
world->getLocalScripts().add(script, ptr);
}
world->removeContainerScripts(ptr);
MWBase::Environment::get().getWindowManager()->onDeleteCustomData(ptr);
refData.setCustomData(nullptr);
// Reset to original position
world->moveObject(ptr, cellRef.getPosition().asVec3());
world->rotateObject(ptr, cellRef.getPosition().asRotationVec3(), MWBase::RotationFlag_none);
}
}
}
Which would kill 10 extra pointless calls in total.