Skip to content

Commit d4a5fff

Browse files
committed
Improve multithreading performance:
* Avoid copying registered MOs lists * Direct function calls instead of recursive flow for multithreaded scripts Update and SyncedUpdate * Double number of threaded lua states
1 parent 1d4d3ae commit d4a5fff

File tree

6 files changed

+47
-36
lines changed

6 files changed

+47
-36
lines changed

Entities/MovableObject.cpp

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1071,16 +1071,6 @@ int MovableObject::UpdateScripts(ThreadScriptsToRun scriptsToRun) {
10711071

10721072
if (status >= 0) {
10731073
status = RunScriptedFunctionInAppropriateScripts("Update", false, true, {}, {}, {}, scriptsToRun);
1074-
1075-
// Perform our synced updates to let multithreaded scripts do anything that interacts with stuff in a non-const way
1076-
// This is identical to non-multithreaded script's Update()
1077-
// TODO - in future, enforce that everything in MultiThreaded Update() is const, so non-const actions must be performed in SyncedUpdate
1078-
// This would require a bunch of Lua binding fuckery, but eventually maybe it'd be possible.
1079-
// I wonder if we can do some SFINAE magic to make the luabindings automagically do a no-op with const objects, to avoid writing the bindings twice
1080-
if (status >= -1 && scriptsToRun == ThreadScriptsToRun::SingleThreaded) {
1081-
// If we're in a SingleThreaded context, we run the MultiThreaded scripts synced updates:
1082-
status = RunScriptedFunctionInAppropriateScripts("SyncedUpdate", false, true, {}, {}, {}, ThreadScriptsToRun::Both);
1083-
}
10841074
}
10851075

10861076
return status;

Lua/LuaAdapters.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -575,7 +575,7 @@ namespace RTE {
575575
scriptedActivity->RunLuaFunction("OnGlobalMessage", {}, { message }, { &wrapper });
576576
}
577577

578-
movableMan.RunLuaFunctionOnAllMOs("OnGlobalMessage", {}, { message }, { &wrapper });
578+
movableMan.RunLuaFunctionOnAllMOs("OnGlobalMessage", true, {}, { message }, { &wrapper });
579579
}
580580

581581
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Managers/LuaMan.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -798,7 +798,10 @@ namespace RTE {
798798
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
799799

800800
void LuaStateWrapper::Update() {
801-
801+
for (MovableObject* mo : m_AddedRegisteredMOs) {
802+
m_RegisteredMOs.insert(mo);
803+
}
804+
m_AddedRegisteredMOs.clear();
802805
}
803806

804807
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Managers/LuaMan.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,13 +93,13 @@ namespace RTE {
9393
/// Registers an MO as using us.
9494
/// </summary>
9595
/// <param name="moToRegister">The MO to register with us. Ownership is NOT transferred!</param>
96-
void RegisterMO(MovableObject* moToRegister) { m_RegisteredMOs.insert(moToRegister); }
96+
void RegisterMO(MovableObject* moToRegister) { m_AddedRegisteredMOs.insert(moToRegister); }
9797

9898
/// <summary>
9999
/// Unregisters an MO as using us.
100100
/// </summary>
101101
/// <param name="moToUnregister">The MO to unregister as using us. Ownership is NOT transferred!</param>
102-
void UnregisterMO(MovableObject *moToUnregister) { m_RegisteredMOs.erase(moToUnregister); }
102+
void UnregisterMO(MovableObject *moToUnregister) { m_RegisteredMOs.erase(moToUnregister); m_AddedRegisteredMOs.erase(moToUnregister); }
103103

104104
/// <summary>
105105
/// Gets a list of the MOs registed as using us.
@@ -290,6 +290,7 @@ namespace RTE {
290290
void Clear();
291291

292292
std::unordered_set<MovableObject *> m_RegisteredMOs; //!< The objects using our lua state.
293+
std::unordered_set<MovableObject *> m_AddedRegisteredMOs; //!< The objects using our lua state that were recently added.
293294

294295
lua_State *m_State;
295296
Entity *m_TempEntity; //!< Temporary holder for an Entity object that we want to pass into the Lua state without fuss. Lets you export objects to lua easily.
@@ -310,7 +311,7 @@ namespace RTE {
310311
RandomGenerator m_RandomGenerator; //!< The random number generator used for this lua state.
311312
};
312313

313-
static constexpr int c_NumThreadedLuaStates = 8;
314+
static constexpr int c_NumThreadedLuaStates = 16;
314315
typedef std::array<LuaStateWrapper, c_NumThreadedLuaStates> LuaStatesArray;
315316

316317
/// <summary>

Managers/MovableMan.cpp

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1568,35 +1568,37 @@ void callLuaFunctionOnMORecursive(MovableObject* mo, const std::string& function
15681568
Attachable* attachable = *attachablrItr;
15691569
++attachablrItr;
15701570

1571-
attachable->RunScriptedFunctionInAppropriateScripts("OnGlobalMessage", false, false, functionEntityArguments, functionLiteralArguments, functionObjectArguments, scriptsToRun);
1571+
attachable->RunScriptedFunctionInAppropriateScripts(functionName, false, false, functionEntityArguments, functionLiteralArguments, functionObjectArguments, scriptsToRun);
15721572
callLuaFunctionOnMORecursive(attachable, functionName, functionEntityArguments, functionLiteralArguments, functionObjectArguments, scriptsToRun);
15731573
}
15741574

15751575
for (auto woundItr = mosr->GetWoundList().begin(); woundItr != mosr->GetWoundList().end(); ) {
15761576
AEmitter* wound = *woundItr;
15771577
++woundItr;
15781578

1579-
wound->RunScriptedFunctionInAppropriateScripts("OnGlobalMessage", false, false, functionEntityArguments, functionLiteralArguments, functionObjectArguments, scriptsToRun);
1579+
wound->RunScriptedFunctionInAppropriateScripts(functionName, false, false, functionEntityArguments, functionLiteralArguments, functionObjectArguments, scriptsToRun);
15801580
callLuaFunctionOnMORecursive(wound, functionName, functionEntityArguments, functionLiteralArguments, functionObjectArguments, scriptsToRun);
15811581
}
15821582
}
15831583

1584-
mo->RunScriptedFunctionInAppropriateScripts("OnGlobalMessage", false, false, functionEntityArguments, functionLiteralArguments, functionObjectArguments, scriptsToRun);
1584+
mo->RunScriptedFunctionInAppropriateScripts(functionName, false, false, functionEntityArguments, functionLiteralArguments, functionObjectArguments, scriptsToRun);
15851585
};
15861586

15871587
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
15881588

1589-
void MovableMan::RunLuaFunctionOnAllMOs(const std::string &functionName, const std::vector<const Entity*> &functionEntityArguments, const std::vector<std::string_view> &functionLiteralArguments, const std::vector<LuabindObjectWrapper*> &functionObjectArguments, ThreadScriptsToRun scriptsToRun) {
1590-
for (Actor* actor : m_AddedActors) {
1591-
callLuaFunctionOnMORecursive(actor, functionName, functionEntityArguments, functionLiteralArguments, functionObjectArguments, scriptsToRun);
1592-
}
1589+
void MovableMan::RunLuaFunctionOnAllMOs(const std::string &functionName, bool includeAdded, const std::vector<const Entity*> &functionEntityArguments, const std::vector<std::string_view> &functionLiteralArguments, const std::vector<LuabindObjectWrapper*> &functionObjectArguments, ThreadScriptsToRun scriptsToRun) {
1590+
if (includeAdded) {
1591+
for (Actor* actor : m_AddedActors) {
1592+
callLuaFunctionOnMORecursive(actor, functionName, functionEntityArguments, functionLiteralArguments, functionObjectArguments, scriptsToRun);
1593+
}
15931594

1594-
for (MovableObject *item : m_AddedItems) {
1595-
callLuaFunctionOnMORecursive(item, functionName, functionEntityArguments, functionLiteralArguments, functionObjectArguments, scriptsToRun);
1596-
}
1595+
for (MovableObject *item : m_AddedItems) {
1596+
callLuaFunctionOnMORecursive(item, functionName, functionEntityArguments, functionLiteralArguments, functionObjectArguments, scriptsToRun);
1597+
}
15971598

1598-
for (MovableObject* particle : m_AddedParticles) {
1599-
callLuaFunctionOnMORecursive(particle, functionName, functionEntityArguments, functionLiteralArguments, functionObjectArguments, scriptsToRun);
1599+
for (MovableObject* particle : m_AddedParticles) {
1600+
callLuaFunctionOnMORecursive(particle, functionName, functionEntityArguments, functionLiteralArguments, functionObjectArguments, scriptsToRun);
1601+
}
16001602
}
16011603

16021604
for (Actor *actor : m_Actors) {
@@ -1728,28 +1730,43 @@ void MovableMan::Update()
17281730
std::deque<MovableObject *>::iterator parIt;
17291731
std::deque<MovableObject *>::iterator midIt;
17301732

1731-
// Update all scripts for all objects
1733+
// Update all multithreaded scripts for all objects
1734+
g_PerformanceMan.StartPerformanceMeasurement(PerformanceMan::ScriptsUpdate);
17321735
{
17331736
ZoneScopedN("Multithreaded Scripts Update");
17341737

1735-
g_PerformanceMan.StartPerformanceMeasurement(PerformanceMan::ScriptsUpdate);
1738+
const std::string threadedUpdate = "Update"; // avoid string reconstruction
1739+
17361740
LuaStatesArray& luaStates = g_LuaMan.GetThreadedScriptStates();
17371741
std::for_each(std::execution::par, luaStates.begin(), luaStates.end(),
17381742
[&](LuaStateWrapper& luaState) {
17391743
g_LuaMan.SetThreadLuaStateOverride(&luaState);
17401744

1741-
// We may have new MOs registered to us by objects creating other things and being initialized
1742-
// So we need to copy this list before using it
1743-
std::unordered_set<MovableObject *> registeredMOs = luaState.GetRegisteredMOs();
1744-
for (MovableObject *mo : registeredMOs) {
1745-
mo->UpdateScripts(ThreadScriptsToRun::MultiThreaded);
1745+
for (MovableObject *mo : luaState.GetRegisteredMOs()) {
1746+
mo->RunScriptedFunctionInAppropriateScripts(threadedUpdate, false, false, {}, {}, {}, ThreadScriptsToRun::MultiThreaded);
17461747
}
17471748

17481749
g_LuaMan.SetThreadLuaStateOverride(nullptr);
17491750
});
1750-
g_PerformanceMan.StopPerformanceMeasurement(PerformanceMan::ScriptsUpdate);
17511751
}
17521752

1753+
{
1754+
ZoneScopedN("Multithreaded Scripts SyncedUpdate");
1755+
1756+
const std::string syncedUpdate = "SyncedUpdate"; // avoid string reconstruction
1757+
1758+
for (LuaStateWrapper& luaState : g_LuaMan.GetThreadedScriptStates()) {
1759+
g_LuaMan.SetThreadLuaStateOverride(&luaState);
1760+
1761+
for (MovableObject* mo : luaState.GetRegisteredMOs()) {
1762+
mo->RunScriptedFunctionInAppropriateScripts(syncedUpdate, false, false, {}, {}, {}, ThreadScriptsToRun::MultiThreaded);
1763+
}
1764+
1765+
g_LuaMan.SetThreadLuaStateOverride(nullptr);
1766+
}
1767+
}
1768+
g_PerformanceMan.StopPerformanceMeasurement(PerformanceMan::ScriptsUpdate);
1769+
17531770
{
17541771
{
17551772
ZoneScopedN("Actors Update");

Managers/MovableMan.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -944,7 +944,7 @@ class MovableMan : public Singleton<MovableMan>, public Serializable {
944944
/// <summary>
945945
/// Runs a lua function on all MOs in the simulation, including owned child MOs.
946946
/// </summary>
947-
void RunLuaFunctionOnAllMOs(const std::string& functionName, const std::vector<const Entity*>& functionEntityArguments = std::vector<const Entity*>(), const std::vector<std::string_view>& functionLiteralArguments = std::vector<std::string_view>(), const std::vector<LuabindObjectWrapper*>& functionObjectArguments = std::vector<LuabindObjectWrapper*>(), ThreadScriptsToRun scriptsToRun = ThreadScriptsToRun::Both);
947+
void RunLuaFunctionOnAllMOs(const std::string& functionName, bool includeAdded, const std::vector<const Entity*>& functionEntityArguments = std::vector<const Entity*>(), const std::vector<std::string_view>& functionLiteralArguments = std::vector<std::string_view>(), const std::vector<LuabindObjectWrapper*>& functionObjectArguments = std::vector<LuabindObjectWrapper*>(), ThreadScriptsToRun scriptsToRun = ThreadScriptsToRun::Both);
948948

949949
/// <summary>
950950
/// Clears all cached lua functions on all MOs, including owned child MOs.

0 commit comments

Comments
 (0)