summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/Bindings/LuaState.cpp72
-rw-r--r--src/Bindings/LuaState.h37
-rw-r--r--src/Server.cpp9
3 files changed, 118 insertions, 0 deletions
diff --git a/src/Bindings/LuaState.cpp b/src/Bindings/LuaState.cpp
index 1509bd19f..385b1f659 100644
--- a/src/Bindings/LuaState.cpp
+++ b/src/Bindings/LuaState.cpp
@@ -43,6 +43,76 @@ const cLuaState::cRet cLuaState::Return = {};
////////////////////////////////////////////////////////////////////////////////
+// cLuaStateTracker:
+
+void cLuaStateTracker::Add(cLuaState & a_LuaState)
+{
+ auto & Instance = Get();
+ cCSLock Lock(Instance.m_CSLuaStates);
+ Instance.m_LuaStates.push_back(&a_LuaState);
+}
+
+
+
+
+void cLuaStateTracker::Del(cLuaState & a_LuaState)
+{
+ auto & Instance = Get();
+ cCSLock Lock(Instance.m_CSLuaStates);
+ Instance.m_LuaStates.erase(
+ std::remove_if(
+ Instance.m_LuaStates.begin(), Instance.m_LuaStates.end(),
+ [&a_LuaState](cLuaStatePtr a_StoredLuaState)
+ {
+ return (&a_LuaState == a_StoredLuaState);
+ }
+ ),
+ Instance.m_LuaStates.end()
+ );
+}
+
+
+
+
+
+AString cLuaStateTracker::GetStats(void)
+{
+ auto & Instance = Get();
+ cCSLock Lock(Instance.m_CSLuaStates);
+ AString res;
+ int Total = 0;
+ for (auto state: Instance.m_LuaStates)
+ {
+ int Mem = 0;
+ if (!state->Call("collectgarbage", "count", cLuaState::Return, Mem))
+ {
+ res.append(Printf("Cannot query memory for state \"%s\"\n", state->GetSubsystemName().c_str()));
+ }
+ else
+ {
+ res.append(Printf("State \"%s\" is using %d KiB of memory\n", state->GetSubsystemName().c_str(), Mem));
+ Total += Mem;
+ }
+ }
+ res.append(Printf("Total memory used by Lua: %d KiB\n", Total));
+ return res;
+}
+
+
+
+
+
+cLuaStateTracker & cLuaStateTracker::Get(void)
+{
+ static cLuaStateTracker Inst; // The singleton
+ return Inst;
+}
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
// cLuaState:
cLuaState::cLuaState(const AString & a_SubsystemName) :
@@ -98,6 +168,7 @@ void cLuaState::Create(void)
m_LuaState = lua_open();
luaL_openlibs(m_LuaState);
m_IsOwned = true;
+ cLuaStateTracker::Add(*this);
}
@@ -133,6 +204,7 @@ void cLuaState::Close(void)
Detach();
return;
}
+ cLuaStateTracker::Del(*this);
lua_close(m_LuaState);
m_LuaState = nullptr;
m_IsOwned = false;
diff --git a/src/Bindings/LuaState.h b/src/Bindings/LuaState.h
index 269a10369..4f688be6c 100644
--- a/src/Bindings/LuaState.h
+++ b/src/Bindings/LuaState.h
@@ -210,6 +210,9 @@ public:
/** Returns true if the m_LuaState is valid */
bool IsValid(void) const { return (m_LuaState != nullptr); }
+
+ /** Returns the name of the subsystem, as specified when the instance was created. */
+ AString GetSubsystemName(void) const { return m_SubsystemName; }
/** Adds the specified path to package.<a_PathVariable> */
void AddPackagePath(const AString & a_PathVariable, const AString & a_Path);
@@ -521,3 +524,37 @@ protected:
+
+/** Keeps track of all create cLuaState instances.
+Can query each for the amount of currently used memory. */
+class cLuaStateTracker
+{
+public:
+ /** Adds the specified Lua state to the internal list of LuaStates. */
+ static void Add(cLuaState & a_LuaState);
+
+ /** Deletes the specified Lua state from the internal list of LuaStates. */
+ static void Del(cLuaState & a_LuaState);
+
+ /** Returns the statistics for all the registered LuaStates. */
+ static AString GetStats(void);
+
+protected:
+ typedef cLuaState * cLuaStatePtr;
+ typedef std::vector<cLuaStatePtr> cLuaStatePtrs;
+
+ /** The internal list of LuaStates.
+ Protected against multithreaded access by m_CSLuaStates. */
+ cLuaStatePtrs m_LuaStates;
+
+ /** Protects m_LuaStates against multithreaded access. */
+ cCriticalSection m_CSLuaStates;
+
+
+ /** Returns the single instance of this class. */
+ static cLuaStateTracker & Get(void);
+};
+
+
+
+
diff --git a/src/Server.cpp b/src/Server.cpp
index a21248695..12c45467d 100644
--- a/src/Server.cpp
+++ b/src/Server.cpp
@@ -145,6 +145,8 @@ cServer::cServer(void) :
m_ShouldLoadOfflinePlayerData(false),
m_ShouldLoadNamedPlayerData(true)
{
+ // Initialize the LuaStateTracker singleton before the app goes multithreaded:
+ cLuaStateTracker::GetStats();
}
@@ -522,6 +524,13 @@ void cServer::ExecuteConsoleCommand(const AString & a_Cmd, cCommandOutputCallbac
a_Output.Finished();
return;
}
+
+ else if (split[0].compare("luastats") == 0)
+ {
+ a_Output.Out(cLuaStateTracker::GetStats());
+ a_Output.Finished();
+ return;
+ }
#if defined(_MSC_VER) && defined(_DEBUG) && defined(ENABLE_LEAK_FINDER)
else if (split[0].compare("dumpmem") == 0)
{