1
0
Fork 0

Merge pull request #2508 from cuberite/LogLuaMemoryStats

Added LuaState tracker and memory stats logging.
This commit is contained in:
worktycho 2015-09-29 13:32:30 +01:00
commit c76a89fbec
3 changed files with 118 additions and 0 deletions

View File

@ -42,6 +42,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:
@ -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;

View File

@ -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);
};

View File

@ -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)
{