sm_dump_handles now shows memory usage

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%401772
This commit is contained in:
David Anderson 2007-12-05 18:07:18 +00:00
parent 41ac66fceb
commit 5ae2a5c4fe
31 changed files with 330 additions and 6 deletions

View File

@ -156,6 +156,11 @@ public:
return m_Data;
}
size_t mem_usage()
{
return m_AllocSize * m_BlockSize * sizeof(cell_t);
}
private:
bool GrowIfNeeded(size_t count)
{

View File

@ -241,6 +241,12 @@ void ConVarManager::OnHandleDestroy(HandleType_t type, void *object)
{
}
bool ConVarManager::GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize)
{
*pSize = sizeof(ConVar);
return true;
}
void ConVarManager::OnRootConsoleCommand(const char *cmdname, const CCommand &command)
{
int argcount = command.ArgC();

View File

@ -82,6 +82,7 @@ public: // SMGlobalClass
void OnSourceModVSPReceived();
public: // IHandleTypeDispatch
void OnHandleDestroy(HandleType_t type, void *object);
bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize);
public: // IPluginsListener
void OnPluginUnloaded(IPlugin *plugin);
public: //IRootConsoleCommand

View File

@ -81,11 +81,29 @@ void MenuManager::OnHandleDestroy(HandleType_t type, void *object)
{
IBaseMenu *menu = (IBaseMenu *)object;
menu->Destroy(false);
} else if (type == m_StyleType) {
}
else if (type == m_StyleType)
{
/* Do nothing */
}
}
bool MenuManager::GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize)
{
if (type == m_MenuType)
{
*pSize = ((IBaseMenu *)object)->GetApproxMemUsage();
return true;
}
else
{
*pSize = ((IMenuStyle *)object)->GetApproxMemUsage();
return true;
}
return false;
}
Handle_t MenuManager::CreateMenuHandle(IBaseMenu *menu, IdentityToken_t *pOwner)
{
if (m_MenuType == NO_HANDLE_TYPE)

View File

@ -91,6 +91,7 @@ public:
unsigned int GetRemainingVoteDelay();
public: //IHandleTypeDispatch
void OnHandleDestroy(HandleType_t type, void *object);
bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize);
public:
HandleError ReadMenuHandle(Handle_t handle, IBaseMenu **menu);
HandleError ReadStyleHandle(Handle_t handle, IMenuStyle **style);

View File

@ -828,3 +828,10 @@ IMenuHandler *CBaseMenu::GetHandler()
{
return m_pHandler;
}
unsigned int CBaseMenu::GetBaseMemUsage()
{
return m_Title.size()
+ m_Strings.GetMemTable()->GetMemUsage()
+ (m_items.size() * sizeof(CItem));
}

View File

@ -135,6 +135,7 @@ public:
virtual unsigned int GetMenuOptionFlags();
virtual void SetMenuOptionFlags(unsigned int flags);
virtual IMenuHandler *GetHandler();
unsigned int GetBaseMemUsage();
private:
void InternalDelete();
protected:

View File

@ -261,6 +261,11 @@ void CRadioStyle::ProcessWatchList()
}
}
unsigned int CRadioStyle::GetApproxMemUsage()
{
return sizeof(CRadioStyle) + (sizeof(CRadioMenuPlayer) * 257);
}
CRadioDisplay::CRadioDisplay()
{
Reset();
@ -494,6 +499,13 @@ bool CRadioDisplay::SetSelectableKeys(unsigned int keymap)
return true;
}
unsigned int CRadioDisplay::GetApproxMemUsage()
{
return sizeof(CRadioDisplay)
+ m_BufferText.size()
+ m_Title.size();
}
CRadioMenu::CRadioMenu(IMenuHandler *pHandler, IdentityToken_t *pOwner) :
CBaseMenu(pHandler, &g_RadioMenuStyle, pOwner)
{
@ -542,6 +554,11 @@ void CRadioMenu::Cancel_Finally()
g_RadioMenuStyle.CancelMenu(this);
}
unsigned int CRadioMenu::GetApproxMemUsage()
{
return sizeof(CRadioMenu) + GetBaseMemUsage();
}
const char *g_RadioNumTable[11] =
{
"0. ", "1. ", "2. ", "3. ", "4. ", "5. ", "6. ", "7. ", "8. ", "9. ", "0. "

View File

@ -82,6 +82,7 @@ public: //IMenuStyle
IMenuPanel *CreatePanel();
IBaseMenu *CreateMenu(IMenuHandler *pHandler, IdentityToken_t *pOwner);
unsigned int GetMaxPageItems();
unsigned int GetApproxMemUsage();
public: //IUserMessageListener
void OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter);
void OnUserMessageSent(int msg_id);
@ -119,6 +120,7 @@ public: //IMenuPanel
unsigned int GetCurrentKey();
bool SetCurrentKey(unsigned int key);
int GetAmountRemaining();
unsigned int GetApproxMemUsage();
public:
void DirectSet(const char *str, int keymap);
private:
@ -141,6 +143,7 @@ public:
unsigned int start_item,
IMenuHandler *alt_handler/* =NULL */);
void Cancel_Finally();
unsigned int GetApproxMemUsage();
};
extern CRadioStyle g_RadioMenuStyle;

View File

@ -163,6 +163,11 @@ bool ValveMenuStyle::DoClientMenu(int client, CBaseMenu *menu, unsigned int firs
return BaseMenuStyle::DoClientMenu(client, menu, first_item, mh, time);
}
unsigned int ValveMenuStyle::GetApproxMemUsage()
{
return sizeof(ValveMenuStyle) + (sizeof(CValveMenuPlayer) * 257);
}
CValveMenuDisplay::CValveMenuDisplay()
{
m_pKv = NULL;
@ -342,6 +347,11 @@ int CValveMenuDisplay::GetAmountRemaining()
return -1;
}
unsigned int CValveMenuDisplay::GetApproxMemUsage()
{
return sizeof(CValveMenuDisplay) + (sizeof(KeyValues) * m_NextPos * 10);
}
CValveMenu::CValveMenu(IMenuHandler *pHandler, IdentityToken_t *pOwner) :
CBaseMenu(pHandler, &g_ValveMenuStyle, pOwner),
m_IntroColor(255, 0, 0, 255)
@ -409,6 +419,11 @@ void CValveMenu::SetMenuOptionFlags(unsigned int flags)
CBaseMenu::SetMenuOptionFlags(flags);
}
unsigned int CValveMenu::GetApproxMemUsage()
{
return sizeof(CValveMenu) + GetBaseMemUsage();
}
const char *g_OptionNumTable[] =
{
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"

View File

@ -74,6 +74,7 @@ public: //IMenuStyle
IMenuPanel *CreatePanel();
IBaseMenu *CreateMenu(IMenuHandler *pHandler, IdentityToken_t *pOwner);
unsigned int GetMaxPageItems();
unsigned int GetApproxMemUsage();
private:
void HookCreateMessage(edict_t *pEdict, DIALOG_TYPE type, KeyValues *kv, IServerPluginCallbacks *plugin);
private:
@ -103,6 +104,7 @@ public:
unsigned int GetCurrentKey();
bool SetCurrentKey(unsigned int key);
int GetAmountRemaining();
unsigned int GetApproxMemUsage();
private:
KeyValues *m_pKv;
unsigned int m_NextPos;
@ -126,6 +128,7 @@ public: //IBaseMenu
unsigned int start_item,
IMenuHandler *alt_handler/* =NULL */);
void SetMenuOptionFlags(unsigned int flags);
unsigned int GetApproxMemUsage();
public: //CBaseMenu
void Cancel_Finally();
private:

View File

@ -58,6 +58,10 @@ public:
*/
void Reset();
inline unsigned int GetMemUsage()
{
return size;
}
private:
unsigned char *membase;

View File

@ -85,3 +85,8 @@ void sm_trie_clear(Trie *trie)
{
trie->k.clear();
}
size_t sm_trie_mem_usage(Trie *trie)
{
return trie->k.mem_usage();
}

View File

@ -41,5 +41,6 @@ bool sm_trie_replace(Trie *trie, const char *key, void *value);
bool sm_trie_retrieve(Trie *trie, const char *key, void **value);
bool sm_trie_delete(Trie *trie, const char *key);
void sm_trie_clear(Trie *trie);
size_t sm_trie_mem_usage(Trie *trie);
#endif //_INCLUDE_SOURCEMOD_SIMPLE_TRIE_H_

View File

@ -56,6 +56,12 @@ public: //IHandleTypeDispatch
CellArray *array = (CellArray *)object;
delete array;
}
bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize)
{
CellArray *pArray = (CellArray *)object;
*pSize = sizeof(CellArray) + pArray->mem_usage();
return true;
}
} s_CellArrayHelpers;
static cell_t CreateArray(IPluginContext *pContext, const cell_t *params)

View File

@ -78,6 +78,12 @@ public:
g_Forwards.ReleaseForward(pForward);
}
bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize)
{
*pSize = sizeof(CForward) + (((IForward *)object)->GetFunctionCount() * 12);
return true;
}
} g_ForwardNativeHelpers;

View File

@ -34,6 +34,7 @@
#include "sm_stringutil.h"
#include "HandleSys.h"
#include <KeyValues.h>
#include "utlbuffer.h"
HandleType_t g_KeyValueType;
@ -63,6 +64,30 @@ public:
pStk->pBase->deleteThis();
delete pStk;
}
int CalcKVSizeR(KeyValues *pv)
{
CUtlBuffer buf;
int size;
pv->RecursiveSaveToFile(buf, 0);
size = buf.TellMaxPut();
buf.Purge();
return size;
}
bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize)
{
KeyValueStack *pStk = (KeyValueStack *)object;
unsigned int size = sizeof(KeyValueStack) + (pStk->pCurRoot.size() * sizeof(KeyValues *));
/* Check how much memory the actual thing takes up */
size += CalcKVSizeR(pStk->pBase);
*pSize = size;
return true;
}
};
KeyValues *SourceModBase::ReadKeyValuesHandle(Handle_t hndl, HandleError *err, bool root)

View File

@ -160,6 +160,12 @@ public:
panel->DeleteThis();
}
virtual bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize)
{
*pSize = ((IMenuPanel *)object)->GetApproxMemUsage();
return true;
}
/**
* It is extremely important that unloaded plugins don't crash.
* Thus, if a plugin unloads, we run through every handler we have.

View File

@ -169,6 +169,12 @@ public:
ParseInfo *parse = (ParseInfo *)object;
delete parse;
}
bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize)
{
*pSize = sizeof(ParseInfo);
return true;
}
};
TextParseGlobals g_TextParseGlobals;

View File

@ -57,6 +57,7 @@ public: //SMGlobalClass, IHandleTypeDispatch, IPluginListener
void OnSourceModAllInitialized();
void OnSourceModShutdown();
void OnHandleDestroy(HandleType_t type, void *object);
bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize);
void OnPluginUnloaded(IPlugin *plugin);
public:
MsgListenerWrapper *CreateListener(IPluginContext *pCtx);
@ -109,6 +110,15 @@ void UsrMessageNatives::OnHandleDestroy(HandleType_t type, void *object)
{
}
bool UsrMessageNatives::GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize)
{
bf_read *pRead = (bf_read *)object;
*pSize = sizeof(bf_read) + pRead->GetNumBytesRead() + pRead->GetNumBytesLeft();
return true;
}
void UsrMessageNatives::OnPluginUnloaded(IPlugin *plugin)
{
MsgWrapperList *pList;

View File

@ -36,6 +36,7 @@
#include "Logger.h"
#include <assert.h>
#include <string.h>
#include "sm_stringutil.h"
HandleSystem g_HandleSys;
@ -996,8 +997,9 @@ bool HandleSystem::TryAndFreeSomeHandles()
void HandleSystem::Dump(HANDLE_REPORTER rep)
{
rep("%-10.10s\t%-20.20s\t%-20.20s", "Handle", "Owner", "Type");
rep("---------------------------------------------");
unsigned int total_size = 0;
rep("%-10.10s\t%-20.20s\t%-20.20s\t%-10.10s", "Handle", "Owner", "Type", "Memory");
rep("--------------------------------------------------------------------------");
for (unsigned int i = 1; i <= m_HandleTail; i++)
{
if (m_Handles[i].set != HandleSet_Used)
@ -1042,11 +1044,24 @@ void HandleSystem::Dump(HANDLE_REPORTER rep)
}
const char *type = "ANON";
QHandleType *pType = &m_Types[m_Handles[i].type];
unsigned int size = 0;
if (pType->nameIdx != -1)
{
type = m_strtab->GetString(pType->nameIdx);
}
rep("0x%08x\t%-20.20s\t%-20.20s", index, owner, type);
if (pType->dispatch->GetDispatchVersion() < HANDLESYS_MEMUSAGE_MIN_VERSION
|| !pType->dispatch->GetHandleApproxSize(m_Handles[i].type, m_Handles[i].object, &size))
{
rep("0x%08x\t%-20.20s\t%-20.20s\t%-10.10s", index, owner, type, "-1");
}
else
{
char buffer[32];
UTIL_Format(buffer, sizeof(buffer), "%d", size);
rep("0x%08x\t%-20.20s\t%-20.20s\t%-10.10s", index, owner, type, buffer);
total_size += size;
}
}
rep("-- Approximately %d bytes of memory are in use by Handles.\n", total_size);
}

View File

@ -48,6 +48,8 @@
#define HANDLESYS_SERIAL_MASK 0xFFFF0000
#define HANDLESYS_HANDLE_MASK 0x0000FFFF
#define HANDLESYS_MEMUSAGE_MIN_VERSION 3
/**
* The QHandle is a nasty structure that compacts the handle system into a big vector.
* The members of the vector each encapsulate one Handle, however, they also act as nodes

View File

@ -123,6 +123,80 @@ void CPlugin::InitIdentity()
}
}
unsigned int CPlugin::CalcMemUsage()
{
unsigned int base_size =
sizeof(CPlugin)
+ sizeof(IdentityToken_t)
+ (m_PhraseFiles.size() * sizeof(unsigned int))
+ (m_dependents.size() * sizeof(CPlugin *))
+ (m_dependsOn.size() * sizeof(CPlugin *))
+ (m_fakeNatives.size() * (sizeof(FakeNative *) + sizeof(FakeNative)))
+ (m_WeakNatives.size() * sizeof(WeakNative))
+ (m_configs.size() * (sizeof(AutoConfig *) + sizeof(AutoConfig)))
+ sm_trie_mem_usage(m_pProps);
for (unsigned int i = 0; i < m_configs.size(); i++)
{
base_size += m_configs[i]->autocfg.size();
base_size += m_configs[i]->folder.size();
}
for (List<String>::iterator i = m_Libraries.begin();
i != m_Libraries.end();
i++)
{
base_size += (*i).size();
}
for (List<String>::iterator i = m_RequiredLibs.begin();
i != m_RequiredLibs.end();
i++)
{
base_size += (*i).size();
}
for (List<FakeNative *>::iterator i = m_fakeNatives.begin();
i != m_fakeNatives.end();
i++)
{
base_size += (*i)->name.size();
}
if (m_plugin != NULL)
{
base_size += sizeof(sp_plugin_t);
base_size += m_plugin->data_size;
base_size += m_plugin->pcode_size;
base_size += (m_plugin->info.natives_num * sizeof(sp_file_natives_t));
base_size += (m_plugin->info.publics_num * sizeof(sp_file_publics_t));
base_size += (m_plugin->info.pubvars_num * sizeof(sp_file_pubvars_t));
base_size += (m_plugin->debug.files_num * sizeof(sp_fdbg_file_t));
base_size += (m_plugin->debug.lines_num * sizeof(sp_fdbg_line_t));
base_size += (m_plugin->debug.syms_num * sizeof(sp_fdbg_symbol_t));
/* We can't get strtab size, oh well. */
}
if (m_ctx.base != NULL)
{
base_size += sizeof(BaseContext);
base_size += m_ctx.base->GetPublicsNum() * sizeof(CFunction);
}
if (m_ctx.ctx != NULL)
{
base_size += m_ctx.ctx->mem_size;
base_size += (m_plugin->debug.files_num * sizeof(sp_debug_file_t));
base_size += (m_plugin->debug.lines_num * sizeof(sp_debug_line_t));
base_size += (m_plugin->debug.syms_num * sizeof(sp_debug_symbol_t));
base_size += (m_plugin->info.pubvars_num * sizeof(sp_pubvar_t));
base_size += (m_plugin->info.publics_num * sizeof(sp_public_t));
base_size += (m_plugin->info.natives_num * sizeof(sp_native_t));
/* We also don't know the JIT code size, oh well. */
}
return base_size;
}
Handle_t CPlugin::GetMyHandle()
{
return m_handle;
@ -1969,6 +2043,12 @@ void CPluginManager::OnHandleDestroy(HandleType_t type, void *object)
/* We don't care about the internal object, actually */
}
bool CPluginManager::GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize)
{
*pSize = ((CPlugin *)object)->CalcMemUsage();
return true;
}
void CPluginManager::RegisterNativesFromCore(sp_nativeinfo_t *natives)
{
for (unsigned int i = 0; natives[i].func != NULL; i++)

View File

@ -169,6 +169,7 @@ public:
unsigned int GetSerial();
const sp_plugin_t *GetPluginStructure();
IdentityToken_t *GetIdentity();
unsigned int CalcMemUsage();
bool SetProperty(const char *prop, void *ptr);
bool GetProperty(const char *prop, void **ptr, bool remove=false);
public:
@ -355,6 +356,7 @@ public: //SMGlobalClass
void OnSourceModShutdown();
public: //IHandleTypeDispatch
void OnHandleDestroy(HandleType_t type, void *object);
bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize);
public: //IRootConsoleCommand
void OnRootConsoleCommand(const char *cmdname, const CCommand &command);
public:

View File

@ -87,6 +87,29 @@ TopMenu::~TopMenu()
delete [] m_clients;
}
unsigned int TopMenu::CalcMemUsage()
{
unsigned int size = sizeof(TopMenu);
size += m_Config.strings.GetMemTable()->MemUsage();
size += (m_Config.cats.size() * sizeof(int));
size += (sizeof(topmenu_player_t) * m_max_clients);
size += (m_SortedCats.size() * sizeof(unsigned int));
size += (m_UnsortedCats.size() * sizeof(unsigned int));
size += (m_Categories.size() * (sizeof(topmenu_category_t *) + sizeof(topmenu_category_t)));
size += (m_Objects.size() * (sizeof(topmenu_object_t *) + sizeof(topmenu_object_t)));
size += m_ObjLookup.mem_usage();
for (size_t i = 0; i < m_Categories.size(); i++)
{
size += m_Categories[i]->obj_list.size() * sizeof(topmenu_object_t *);
size += m_Categories[i]->sorted.size() * sizeof(topmenu_object_t *);
size += m_Categories[i]->unsorted.size() * sizeof(topmenu_object_t *);
}
return size;
}
void TopMenu::OnClientConnected(int client)
{
if (m_clients == NULL)

View File

@ -146,6 +146,8 @@ public: //ITextListener_SMC
SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name);
SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value);
SMCResult ReadSMC_LeavingSection(const SMCStates *states);
public:
unsigned int CalcMemUsage();
private:
void SortCategoriesIfNeeded();
void SortCategoryIfNeeded(unsigned int category);

View File

@ -58,6 +58,10 @@ public:
*/
void Reset();
inline unsigned int MemUsage()
{
return size;
}
private:
unsigned char *membase;

View File

@ -43,6 +43,11 @@ public:
ITopMenu *pTopMenu = (ITopMenu *)object;
g_TopMenus.DestroyTopMenu(pTopMenu);
}
bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize)
{
*pSize = ((TopMenu *)object)->CalcMemUsage();
return true;
}
} s_TopMenuHandle;
void Initialize_Natives()

View File

@ -52,7 +52,7 @@
#include <sp_vm_types.h>
#define SMINTERFACE_HANDLESYSTEM_NAME "IHandleSys"
#define SMINTERFACE_HANDLESYSTEM_VERSION 2
#define SMINTERFACE_HANDLESYSTEM_VERSION 3
/** Specifies no Identity */
#define DEFAULT_IDENTITY NULL
@ -195,8 +195,25 @@ namespace SourceMod
public:
/**
* @brief Called when destroying a handle. Must be implemented.
*
* @param type Handle type.
* @param object Handle internal object.
*/
virtual void OnHandleDestroy(HandleType_t type, void *object) =0;
/**
* @brief Called to get the size of a handle's memory usage in bytes.
* Implementation is optional.
*
* @param type Handle type.
* @param object Handle internal object.
* @param pSize Pointer to store the approximate memory usage in bytes.
* @return True on success, false if not implemented.
*/
virtual bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize)
{
return false;
}
};
/**

View File

@ -36,7 +36,7 @@
#include <IHandleSys.h>
#define SMINTERFACE_MENUMANAGER_NAME "IMenuManager"
#define SMINTERFACE_MENUMANAGER_VERSION 13
#define SMINTERFACE_MENUMANAGER_VERSION 14
/**
* @file IMenuManager.h
@ -323,6 +323,13 @@ namespace SourceMod
* -1, then the panel has no text limit.
*/
virtual int GetAmountRemaining() =0;
/**
* @brief For the Handle system, returns approximate memory usage.
*
* @return Approximate number of bytes being used.
*/
virtual unsigned int GetApproxMemUsage() =0;
};
/**
@ -406,6 +413,13 @@ namespace SourceMod
* @return Handle_t pointing to this object.
*/
virtual Handle_t GetHandle() =0;
/**
* @brief For the Handle system, returns approximate memory usage.
*
* @return Approximate number of bytes being used.
*/
virtual unsigned int GetApproxMemUsage() =0;
};
/**
@ -597,6 +611,13 @@ namespace SourceMod
unsigned int time,
unsigned int start_item,
IMenuHandler *alt_handler=NULL) =0;
/**
* @brief For the Handle system, returns approximate memory usage.
*
* @return Approximate number of bytes being used.
*/
virtual unsigned int GetApproxMemUsage() =0;
};
/**

View File

@ -877,6 +877,13 @@ private:
return x_check_multi(offsets, count, to_check+1);
}
public:
size_t mem_usage()
{
return (sizeof(KTrieNode) * (m_baseSize))
+ m_stSize
+ sizeof(KTrieNode);
}
private:
KTrieNode *m_base; /* Base array for the sparse tables */
KTrieNode *m_empty; /* Special case for empty strings */