From d3043b7e63cbb3efb0d247a8014dc486c571a444 Mon Sep 17 00:00:00 2001 From: CrosRoad95 Date: Thu, 18 Mar 2021 16:13:29 +0100 Subject: [PATCH 01/10] profiler --- Server/mods/deathmatch/StdInc.h | 1 + Server/mods/deathmatch/logic/CGame.cpp | 10 +++ Server/mods/deathmatch/logic/CGame.h | 3 + .../deathmatch/logic/CPerformanceRecorder.cpp | 74 +++++++++++++++++++ .../deathmatch/logic/CPerformanceRecorder.h | 36 +++++++++ .../deathmatch/logic/luadefs/CLuaUtilDefs.cpp | 30 ++++++++ .../deathmatch/logic/luadefs/CLuaUtilDefs.h | 4 + 7 files changed, 158 insertions(+) create mode 100644 Server/mods/deathmatch/logic/CPerformanceRecorder.cpp create mode 100644 Server/mods/deathmatch/logic/CPerformanceRecorder.h diff --git a/Server/mods/deathmatch/StdInc.h b/Server/mods/deathmatch/StdInc.h index 4fe445cd8c7..949d002056c 100644 --- a/Server/mods/deathmatch/StdInc.h +++ b/Server/mods/deathmatch/StdInc.h @@ -177,6 +177,7 @@ struct SAclRequest; // Logic includes #include "ASE.h" +#include "CPerformanceRecorder.h" #include "ASEQuerySDK.h" #include "CAccessControlList.h" #include "CAccessControlListGroup.h" diff --git a/Server/mods/deathmatch/logic/CGame.cpp b/Server/mods/deathmatch/logic/CGame.cpp index b442891d667..848efcab92b 100644 --- a/Server/mods/deathmatch/logic/CGame.cpp +++ b/Server/mods/deathmatch/logic/CGame.cpp @@ -141,6 +141,7 @@ CGame::CGame() : m_FloodProtect(4, 30000, 30000) // Max of 4 connecti m_pBuildingRemovalManager = NULL; m_pCustomWeaponManager = NULL; m_pFunctionUseLogger = NULL; + m_pPerformanceRecorder = nullptr; #ifdef WITH_OBJECT_SYNC m_pObjectSync = NULL; #endif @@ -320,6 +321,7 @@ CGame::~CGame() SAFE_DELETE(m_pSettings); SAFE_DELETE(m_pRPCFunctions); SAFE_DELETE(m_pWaterManager); + SAFE_DELETE(m_pPerformanceRecorder); SAFE_DELETE(m_pWeaponStatsManager); SAFE_DELETE(m_pBuildingRemovalManager); SAFE_DELETE(m_pCustomWeaponManager); @@ -374,6 +376,13 @@ void CGame::HandleInput(char* szCommand) void CGame::DoPulse() { + CPerformanceRecorder::Sample sample("DoPulse"); + { + CPerformanceRecorder::Sample sample("Foo test"); + for (int i = 0; i < 10000000; i++) + { + } + } // Lock the critical section so http server won't interrupt in the middle of our pulse Lock(); @@ -511,6 +520,7 @@ bool CGame::Start(int iArgumentCount, char* szArguments[]) m_pTeamManager = new CTeamManager; m_pPedManager = new CPedManager; m_pWaterManager = new CWaterManager; + m_pPerformanceRecorder = new CPerformanceRecorder; m_pScriptDebugging = new CScriptDebugging(); m_pMapManager = new CMapManager(m_pBlipManager, m_pObjectManager, m_pPickupManager, m_pPlayerManager, m_pRadarAreaManager, m_pMarkerManager, m_pVehicleManager, m_pTeamManager, m_pPedManager, m_pColManager, m_pWaterManager, m_pClock, m_pGroups, diff --git a/Server/mods/deathmatch/logic/CGame.h b/Server/mods/deathmatch/logic/CGame.h index f8ab006cb05..00c402aa3a7 100644 --- a/Server/mods/deathmatch/logic/CGame.h +++ b/Server/mods/deathmatch/logic/CGame.h @@ -102,6 +102,7 @@ class CVehicleManager; class CZoneNames; class CLanBroadcast; class CWaterManager; +class CPerformanceRecorder; class CTrainTrackManager; class CWeaponStatManager; class CBuildingRemovalManager; @@ -245,6 +246,7 @@ class CGame CZoneNames* GetZoneNames() { return m_pZoneNames; } CClock* GetClock() { return m_pClock; } CWaterManager* GetWaterManager() { return m_pWaterManager; } + CPerformanceRecorder* GetPerformanceRecorder() { return m_pPerformanceRecorder; } CLightsyncManager* GetLightSyncManager() { return &m_lightsyncManager; } CWeaponStatManager* GetWeaponStatManager() { return m_pWeaponStatsManager; } CBuildingRemovalManager* GetBuildingRemovalManager() { return m_pBuildingRemovalManager; } @@ -555,6 +557,7 @@ class CGame CRPCFunctions* m_pRPCFunctions; CLanBroadcast* m_pLanBroadcast; CWaterManager* m_pWaterManager; + CPerformanceRecorder* m_pPerformanceRecorder; CWeaponStatManager* m_pWeaponStatsManager; CBuildingRemovalManager* m_pBuildingRemovalManager; diff --git a/Server/mods/deathmatch/logic/CPerformanceRecorder.cpp b/Server/mods/deathmatch/logic/CPerformanceRecorder.cpp new file mode 100644 index 00000000000..7541fe0783b --- /dev/null +++ b/Server/mods/deathmatch/logic/CPerformanceRecorder.cpp @@ -0,0 +1,74 @@ +#include "StdInc.h" + +CPerformanceRecorder::CPerformanceRecorder() +{ +} + +CPerformanceRecorder::~CPerformanceRecorder() +{ +} + +void CPerformanceRecorder::Start() +{ + m_bRecordPerformance = true; + g_pGame->GetPerformanceRecorder()->m_strStream << '['; +} + +void CPerformanceRecorder::Stop() +{ + m_bRecordPerformance = false; +} + +void CPerformanceRecorder::Clear() +{ + m_strStream.clear(); + m_start = GetTimeUs(); +} + +std::string CPerformanceRecorder::GetResult() +{ + return m_strStream.str() + "]"; +} + +CPerformanceRecorder::Sample::Sample(const char* name) : m_szName(name), m_start(GetTimeUs()) +{ + m_pObject = json_object_new_object(); +} +// +//{"name": "aaaaaaaaaaa", "cat": "PERF", "ph": "B", "pid": 22630, "tid": 22630, "ts": 829, "cname": "foo"}, +//{"name": "aaaaaaaaaaa", "cat": "PERF", "ph": "E", "pid": 22630, "tid": 22630, "ts": 2000, "cname": "foo"}, +void CPerformanceRecorder::Sample::Set(const char* szKey, const char* value) +{ + if (m_pObject) + { + json_object_object_add(m_pObject, szKey, json_object_new_string(value)); + } +} +CPerformanceRecorder::Sample::~Sample() +{ + if (m_pObject) + { + json_object* m_pObjectStart = json_object_new_object(); + json_object_object_add(m_pObjectStart, "name", json_object_new_string(m_szName)); + json_object_object_add(m_pObjectStart, "cat", json_object_new_string("PERF")); + json_object_object_add(m_pObjectStart, "ph", json_object_new_string("B")); + json_object_object_add(m_pObjectStart, "ts", json_object_new_int(m_start)); + json_object_object_add(m_pObjectStart, "pid", json_object_new_int(GetCurrentThreadId())); + + + Set("name", m_szName); + Set("cat", "PERF"); + Set("ph", "E"); + json_object_object_add(m_pObject, "ts", json_object_new_int(GetTimeUs())); + json_object_object_add(m_pObject, "pid", json_object_new_int(GetCurrentThreadId())); + + int flags = JSON_C_TO_STRING_PLAIN; + + g_pGame->GetPerformanceRecorder()->m_strStream << json_object_to_json_string_ext(m_pObjectStart, flags) << ','; + g_pGame->GetPerformanceRecorder()->m_strStream << json_object_to_json_string_ext(m_pObject, flags) << ','; + json_object_put(m_pObject); + json_object_put(m_pObjectStart); + } + + int a = 5; +} diff --git a/Server/mods/deathmatch/logic/CPerformanceRecorder.h b/Server/mods/deathmatch/logic/CPerformanceRecorder.h new file mode 100644 index 00000000000..6d4e86452de --- /dev/null +++ b/Server/mods/deathmatch/logic/CPerformanceRecorder.h @@ -0,0 +1,36 @@ +class CPerformanceRecorder +{ + friend class Sample; + +public: + CPerformanceRecorder(); + ~CPerformanceRecorder(); + + void Start(); + void Stop(); + void Clear(); + + bool IsDuringPerformanceRecording() const { return m_bRecordPerformance; } + std::string GetResult(); + + + class Sample + { + public: + Sample(const char* name); + ~Sample(); + + void Set(const char* szKey, const char* value); + private: + const char* m_szName; + TIMEUS m_start; + json_object* m_pObject = nullptr; + }; + + +private: + bool m_bRecordPerformance = false; + TIMEUS m_start; + + std::stringstream m_strStream; +}; diff --git a/Shared/mods/deathmatch/logic/luadefs/CLuaUtilDefs.cpp b/Shared/mods/deathmatch/logic/luadefs/CLuaUtilDefs.cpp index bc1b90618f9..9745e6e5f66 100644 --- a/Shared/mods/deathmatch/logic/luadefs/CLuaUtilDefs.cpp +++ b/Shared/mods/deathmatch/logic/luadefs/CLuaUtilDefs.cpp @@ -46,6 +46,9 @@ void CLuaUtilDefs::LoadFunctions() // Utility functions {"gettok", GetTok}, {"tocolor", tocolor}, + {"startRecordPerformance", ArgumentParser}, + {"stopRecordPerformance", ArgumentParser}, + {"getRecordedPerformance", ArgumentParser}, }; // Add functions @@ -711,3 +714,30 @@ int CLuaUtilDefs::tocolor(lua_State* luaVM) lua_pushnumber(luaVM, static_cast(ulColor)); return 1; } + +bool CLuaUtilDefs::StartRecordPerformance(std::optional bClear) +{ + if (g_pGame->GetPerformanceRecorder()->IsDuringPerformanceRecording()) + return false; + + g_pGame->GetPerformanceRecorder()->Start(); + + if (bClear.value_or(false)) + g_pGame->GetPerformanceRecorder()->Clear(); + + return true; +} + +bool CLuaUtilDefs::StopRecordPerformance() +{ + if (!g_pGame->GetPerformanceRecorder()->IsDuringPerformanceRecording()) + return false; + + g_pGame->GetPerformanceRecorder()->Stop(); + return true; +} + +std::string CLuaUtilDefs::GetRecordedPerformance() +{ + return g_pGame->GetPerformanceRecorder()->GetResult(); +} diff --git a/Shared/mods/deathmatch/logic/luadefs/CLuaUtilDefs.h b/Shared/mods/deathmatch/logic/luadefs/CLuaUtilDefs.h index 849011a94d4..3d0f76f987a 100644 --- a/Shared/mods/deathmatch/logic/luadefs/CLuaUtilDefs.h +++ b/Shared/mods/deathmatch/logic/luadefs/CLuaUtilDefs.h @@ -52,4 +52,8 @@ class CLuaUtilDefs : public CLuaDefs // Utility functions LUA_DECLARE(GetTok); LUA_DECLARE(tocolor); + + static bool StartRecordPerformance(std::optional bClear); + static bool StopRecordPerformance(); + static std::string GetRecordedPerformance(); }; From 108f2c2d73555b6baa1e2030786cded0ce584335 Mon Sep 17 00:00:00 2001 From: CrosRoad95 Date: Thu, 18 Mar 2021 20:17:50 +0100 Subject: [PATCH 02/10] profiling --- Server/mods/deathmatch/logic/ASE.cpp | 1 + .../logic/CAccessControlListManager.cpp | 1 + .../mods/deathmatch/logic/CAccountManager.cpp | 1 + Server/mods/deathmatch/logic/CBanManager.cpp | 1 + .../mods/deathmatch/logic/CBlendedWeather.cpp | 1 + .../deathmatch/logic/CDatabaseManager.cpp | 1 + Server/mods/deathmatch/logic/CElement.cpp | 1 + .../mods/deathmatch/logic/CElementDeleter.cpp | 2 + Server/mods/deathmatch/logic/CGame.cpp | 27 +++++----- .../deathmatch/logic/CLightsyncManager.cpp | 2 + Server/mods/deathmatch/logic/CMapManager.cpp | 1 + Server/mods/deathmatch/logic/CPedSync.cpp | 1 + .../deathmatch/logic/CPerformanceRecorder.cpp | 52 ++++++++++++++----- .../deathmatch/logic/CPerformanceRecorder.h | 23 ++++++-- .../mods/deathmatch/logic/CPlayerManager.cpp | 2 + .../deathmatch/logic/CRegistryManager.cpp | 1 + .../deathmatch/logic/CResourceManager.cpp | 2 + .../logic/CStaticFunctionDefinitions.cpp | 4 ++ .../logic/CUnoccupiedVehicleSync.cpp | 1 + .../mods/deathmatch/logic/lua/CLuaManager.cpp | 2 + .../deathmatch/logic/lua/CLuaTimerManager.cpp | 8 +++ .../deathmatch/utils/CFunctionUseLogger.cpp | 1 + .../logic/CLatentTransferManager.cpp | 1 + 23 files changed, 107 insertions(+), 30 deletions(-) diff --git a/Server/mods/deathmatch/logic/ASE.cpp b/Server/mods/deathmatch/logic/ASE.cpp index a7636980298..bec9c350bc8 100644 --- a/Server/mods/deathmatch/logic/ASE.cpp +++ b/Server/mods/deathmatch/logic/ASE.cpp @@ -134,6 +134,7 @@ bool ASE::SetPortEnabled(bool bInternetEnabled, bool bLanEnabled) void ASE::DoPulse() { + CPerformanceRecorder::Sample sample("ASE::DoPulse"); if (m_SocketList.empty()) return; diff --git a/Server/mods/deathmatch/logic/CAccessControlListManager.cpp b/Server/mods/deathmatch/logic/CAccessControlListManager.cpp index c5b89d43bb8..f897e08d989 100644 --- a/Server/mods/deathmatch/logic/CAccessControlListManager.cpp +++ b/Server/mods/deathmatch/logic/CAccessControlListManager.cpp @@ -304,6 +304,7 @@ CAccessControlList* CAccessControlListManager::GetACL(const char* szACLName) void CAccessControlListManager::DoPulse() { + CPerformanceRecorder::Sample sample("CAccessControlListManager::DoPulse"); // Clear cache every 12 hours or if dirty if (m_bReadCacheDirty || GetTickCount64_() - m_llLastTimeReadCacheCleared > 1000 * 60 * 60 * 12) ClearReadCache(); diff --git a/Server/mods/deathmatch/logic/CAccountManager.cpp b/Server/mods/deathmatch/logic/CAccountManager.cpp index 101b9d66281..c0a77675bac 100644 --- a/Server/mods/deathmatch/logic/CAccountManager.cpp +++ b/Server/mods/deathmatch/logic/CAccountManager.cpp @@ -135,6 +135,7 @@ void CAccountManager::DoPulse() // Save it only once in a while whenever something has changed if (m_bChangedSinceSaved && GetTickCount64_() > m_llLastTimeSaved + 15000) { + CPerformanceRecorder::Sample sample("CAccountManager::DoPulse"); // Save it Save(); } diff --git a/Server/mods/deathmatch/logic/CBanManager.cpp b/Server/mods/deathmatch/logic/CBanManager.cpp index 369378daea6..69712392986 100644 --- a/Server/mods/deathmatch/logic/CBanManager.cpp +++ b/Server/mods/deathmatch/logic/CBanManager.cpp @@ -39,6 +39,7 @@ CBanManager::~CBanManager() void CBanManager::DoPulse() { + CPerformanceRecorder::Sample sample("CBanManager::DoPulse"); time_t tTime = time(NULL); if (tTime > m_tUpdate) diff --git a/Server/mods/deathmatch/logic/CBlendedWeather.cpp b/Server/mods/deathmatch/logic/CBlendedWeather.cpp index 15b4d6d128e..1e42561de8d 100644 --- a/Server/mods/deathmatch/logic/CBlendedWeather.cpp +++ b/Server/mods/deathmatch/logic/CBlendedWeather.cpp @@ -27,6 +27,7 @@ CBlendedWeather::CBlendedWeather(CClock* pClock) void CBlendedWeather::DoPulse() { + CPerformanceRecorder::Sample sample("CBlendedWeather::DoPulse"); Update(); } diff --git a/Server/mods/deathmatch/logic/CDatabaseManager.cpp b/Server/mods/deathmatch/logic/CDatabaseManager.cpp index b8b6311adfe..82b6a94c004 100644 --- a/Server/mods/deathmatch/logic/CDatabaseManager.cpp +++ b/Server/mods/deathmatch/logic/CDatabaseManager.cpp @@ -119,6 +119,7 @@ CDatabaseManagerImpl::~CDatabaseManagerImpl() /////////////////////////////////////////////////////////////// void CDatabaseManagerImpl::DoPulse() { + CPerformanceRecorder::Sample sample("CDatabaseManager::DoPulse"); m_JobQueue->DoPulse(); } diff --git a/Server/mods/deathmatch/logic/CElement.cpp b/Server/mods/deathmatch/logic/CElement.cpp index 90b64a1983f..d375810e31b 100644 --- a/Server/mods/deathmatch/logic/CElement.cpp +++ b/Server/mods/deathmatch/logic/CElement.cpp @@ -422,6 +422,7 @@ bool CElement::AddEvent(CLuaMain* pLuaMain, const char* szName, const CLuaFuncti bool CElement::CallEvent(const char* szName, const CLuaArguments& Arguments, CPlayer* pCaller) { + CPerformanceRecorder::EventSample sample(szName); if (!g_pGame->GetDebugHookManager()->OnPreEvent(szName, Arguments, this, pCaller)) return false; diff --git a/Server/mods/deathmatch/logic/CElementDeleter.cpp b/Server/mods/deathmatch/logic/CElementDeleter.cpp index 9a6aa286986..64a3d452eb4 100644 --- a/Server/mods/deathmatch/logic/CElementDeleter.cpp +++ b/Server/mods/deathmatch/logic/CElementDeleter.cpp @@ -44,6 +44,8 @@ void CElementDeleter::Delete(class CElement* pElement, bool bUnlink, bool bUpdat void CElementDeleter::DoDeleteAll() { + CPerformanceRecorder::Sample sample("CElementDeleter::DoDeleteAll"); + sample.SetArg("Deleted elements", m_List.size()); // This depends on CElementDeleter::Unreference() being called in ~CElement() while (!m_List.empty()) delete *m_List.begin(); diff --git a/Server/mods/deathmatch/logic/CGame.cpp b/Server/mods/deathmatch/logic/CGame.cpp index 848efcab92b..7f187500199 100644 --- a/Server/mods/deathmatch/logic/CGame.cpp +++ b/Server/mods/deathmatch/logic/CGame.cpp @@ -376,13 +376,6 @@ void CGame::HandleInput(char* szCommand) void CGame::DoPulse() { - CPerformanceRecorder::Sample sample("DoPulse"); - { - CPerformanceRecorder::Sample sample("Foo test"); - for (int i = 0; i < 10000000; i++) - { - } - } // Lock the critical section so http server won't interrupt in the middle of our pulse Lock(); @@ -416,11 +409,16 @@ void CGame::DoPulse() CSimControl::DoPulse(); CNetBufferWatchDog::DoPulse(); + CPerformanceRecorder::Sample sample("DoPulse"); CLOCK_SET_SECTION("CGame::DoPulse"); - CLOCK1("HTTPDownloadManager"); - GetRemoteCalls()->ProcessQueuedFiles(); - g_pNetServer->GetHTTPDownloadManager(EDownloadMode::ASE)->ProcessQueuedFiles(); - UNCLOCK1("HTTPDownloadManager"); + { + CPerformanceRecorder::Sample sample("HTTPDownloadManager"); + + CLOCK1("HTTPDownloadManager"); + GetRemoteCalls()->ProcessQueuedFiles(); + g_pNetServer->GetHTTPDownloadManager(EDownloadMode::ASE)->ProcessQueuedFiles(); + UNCLOCK1("HTTPDownloadManager"); + } CLOCK_CALL1(m_pPlayerManager->DoPulse();); @@ -429,6 +427,7 @@ void CGame::DoPulse() if (m_pLanBroadcast) { + CPerformanceRecorder::Sample sample("Lan broadcast"); CLOCK_CALL1(m_pLanBroadcast->DoPulse();); } @@ -447,6 +446,7 @@ void CGame::DoPulse() // Handle the traffic light sync if (m_bTrafficLightsLocked == false) { + CPerformanceRecorder::Sample sample("ProcessTrafficLights"); CLOCK_CALL1(ProcessTrafficLights(llCurrentTime);); } @@ -483,7 +483,10 @@ void CGame::DoPulse() CLOCK_CALL1(m_pLatentTransferManager->DoPulse();); - CLOCK_CALL1(m_pAsyncTaskScheduler->CollectResults()); + { + CPerformanceRecorder::Sample sample("CAsyncTaskScheduler::CollectResults"); + CLOCK_CALL1(m_pAsyncTaskScheduler->CollectResults()); + } CLOCK_CALL1(m_pMapManager->GetWeather()->DoPulse();); diff --git a/Server/mods/deathmatch/logic/CLightsyncManager.cpp b/Server/mods/deathmatch/logic/CLightsyncManager.cpp index 056497519d9..7e9acce1025 100644 --- a/Server/mods/deathmatch/logic/CLightsyncManager.cpp +++ b/Server/mods/deathmatch/logic/CLightsyncManager.cpp @@ -76,6 +76,8 @@ void CLightsyncManager::DoPulse() // are also storing the delta context in what it happened, so we only consider the health unchanged // when we find the marker with the same context value. + CPerformanceRecorder::Sample sample("CLightsyncManager::DoPulse"); + if (g_pBandwidthSettings->bLightSyncEnabled == false) return; diff --git a/Server/mods/deathmatch/logic/CMapManager.cpp b/Server/mods/deathmatch/logic/CMapManager.cpp index 4debe64d676..e575c95cf42 100644 --- a/Server/mods/deathmatch/logic/CMapManager.cpp +++ b/Server/mods/deathmatch/logic/CMapManager.cpp @@ -55,6 +55,7 @@ CMapManager::~CMapManager() void CMapManager::DoPulse() { + CPerformanceRecorder::Sample sample("CMapManager::DoPulse"); // Do the respawning checks DoRespawning(); } diff --git a/Server/mods/deathmatch/logic/CPedSync.cpp b/Server/mods/deathmatch/logic/CPedSync.cpp index 490a137de44..1978dc9e8b1 100644 --- a/Server/mods/deathmatch/logic/CPedSync.cpp +++ b/Server/mods/deathmatch/logic/CPedSync.cpp @@ -19,6 +19,7 @@ CPedSync::CPedSync(CPlayerManager* pPlayerManager, CPedManager* pPedManager) void CPedSync::DoPulse() { + CPerformanceRecorder::Sample sample("CPedSync::DoPulse"); // Time to check for players that should no longer be syncing a ped or peds that should be synced? if (m_UpdateTimer.Get() > 500) { diff --git a/Server/mods/deathmatch/logic/CPerformanceRecorder.cpp b/Server/mods/deathmatch/logic/CPerformanceRecorder.cpp index 7541fe0783b..29c931359e7 100644 --- a/Server/mods/deathmatch/logic/CPerformanceRecorder.cpp +++ b/Server/mods/deathmatch/logic/CPerformanceRecorder.cpp @@ -30,37 +30,63 @@ std::string CPerformanceRecorder::GetResult() return m_strStream.str() + "]"; } +CPerformanceRecorder::FunctionSample::FunctionSample(const char* name) : Sample("") +{ + m_szName = std::string("Native function: ") + name; + m_szCategory = "function"; +} + +CPerformanceRecorder::EventSample::EventSample(const char* name) : Sample("") +{ + m_szName = std::string("Event: ") + name; + m_szCategory = "event"; +} + CPerformanceRecorder::Sample::Sample(const char* name) : m_szName(name), m_start(GetTimeUs()) { - m_pObject = json_object_new_object(); + if (g_pGame->GetPerformanceRecorder() ->m_bRecordPerformance) + m_pObject = json_object_new_object(); } // //{"name": "aaaaaaaaaaa", "cat": "PERF", "ph": "B", "pid": 22630, "tid": 22630, "ts": 829, "cname": "foo"}, //{"name": "aaaaaaaaaaa", "cat": "PERF", "ph": "E", "pid": 22630, "tid": 22630, "ts": 2000, "cname": "foo"}, -void CPerformanceRecorder::Sample::Set(const char* szKey, const char* value) + +void CPerformanceRecorder::Sample::SetArg(const char* szKey, const char* value) { - if (m_pObject) - { - json_object_object_add(m_pObject, szKey, json_object_new_string(value)); - } + if (!m_pObjectArgs) + m_pObjectArgs = json_object_new_object(); + + json_object_object_add(m_pObjectArgs, szKey, json_object_new_string(value)); } + +void CPerformanceRecorder::Sample::SetArg(const char* szKey, int value) +{ + if (!m_pObjectArgs) + m_pObjectArgs = json_object_new_object(); + + json_object_object_add(m_pObjectArgs, szKey, json_object_new_int(value)); +} + CPerformanceRecorder::Sample::~Sample() { if (m_pObject) { json_object* m_pObjectStart = json_object_new_object(); - json_object_object_add(m_pObjectStart, "name", json_object_new_string(m_szName)); - json_object_object_add(m_pObjectStart, "cat", json_object_new_string("PERF")); + json_object_object_add(m_pObjectStart, "name", json_object_new_string(m_szName.c_str())); + json_object_object_add(m_pObjectStart, "cat", json_object_new_string(m_szCategory)); json_object_object_add(m_pObjectStart, "ph", json_object_new_string("B")); json_object_object_add(m_pObjectStart, "ts", json_object_new_int(m_start)); json_object_object_add(m_pObjectStart, "pid", json_object_new_int(GetCurrentThreadId())); - - Set("name", m_szName); - Set("cat", "PERF"); - Set("ph", "E"); + json_object_object_add(m_pObject, "name", json_object_new_string(m_szName.c_str())); + json_object_object_add(m_pObject, "cat", json_object_new_string(m_szCategory)); + json_object_object_add(m_pObject, "ph", json_object_new_string("E")); json_object_object_add(m_pObject, "ts", json_object_new_int(GetTimeUs())); json_object_object_add(m_pObject, "pid", json_object_new_int(GetCurrentThreadId())); + if (m_pObjectArgs) + { + json_object_object_add(m_pObjectStart, "args", m_pObjectArgs); + } int flags = JSON_C_TO_STRING_PLAIN; @@ -69,6 +95,4 @@ CPerformanceRecorder::Sample::~Sample() json_object_put(m_pObject); json_object_put(m_pObjectStart); } - - int a = 5; } diff --git a/Server/mods/deathmatch/logic/CPerformanceRecorder.h b/Server/mods/deathmatch/logic/CPerformanceRecorder.h index 6d4e86452de..a1748156637 100644 --- a/Server/mods/deathmatch/logic/CPerformanceRecorder.h +++ b/Server/mods/deathmatch/logic/CPerformanceRecorder.h @@ -13,20 +13,35 @@ class CPerformanceRecorder bool IsDuringPerformanceRecording() const { return m_bRecordPerformance; } std::string GetResult(); - class Sample { public: Sample(const char* name); ~Sample(); - void Set(const char* szKey, const char* value); + void SetArg(const char* szKey, const char* value); + void SetArg(const char* szKey, int value); + + protected: + std::string m_szName; + const char* m_szCategory = "default"; private: - const char* m_szName; - TIMEUS m_start; + TIMEUS m_start = 0; json_object* m_pObject = nullptr; + json_object* m_pObjectArgs = nullptr; }; + class FunctionSample : public Sample + { + public: + FunctionSample(const char* name); + }; + + class EventSample : public Sample + { + public: + EventSample(const char* name); + }; private: bool m_bRecordPerformance = false; diff --git a/Server/mods/deathmatch/logic/CPlayerManager.cpp b/Server/mods/deathmatch/logic/CPlayerManager.cpp index 2d10e3693ef..3b83349fdbc 100644 --- a/Server/mods/deathmatch/logic/CPlayerManager.cpp +++ b/Server/mods/deathmatch/logic/CPlayerManager.cpp @@ -26,6 +26,7 @@ CPlayerManager::~CPlayerManager() void CPlayerManager::DoPulse() { + CPerformanceRecorder::Sample sample("CPlayerManager::DoPulse"); PulseZombieCheck(); list::const_iterator iter = m_Players.begin(); @@ -33,6 +34,7 @@ void CPlayerManager::DoPulse() { (*iter)->DoPulse(); } + sample.SetArg("Players", m_Players.size()); } void CPlayerManager::PulseZombieCheck() diff --git a/Server/mods/deathmatch/logic/CRegistryManager.cpp b/Server/mods/deathmatch/logic/CRegistryManager.cpp index a992039a2df..628601a1c0c 100644 --- a/Server/mods/deathmatch/logic/CRegistryManager.cpp +++ b/Server/mods/deathmatch/logic/CRegistryManager.cpp @@ -21,6 +21,7 @@ CRegistryManager::~CRegistryManager() void CRegistryManager::DoPulse() { + CPerformanceRecorder::Sample sample("CRegistryManager::DoPulse"); // End automatic transactions started in the previous pulse for (unsigned int i = 0; i < m_RegistryList.size(); i++) m_RegistryList[i]->EndAutomaticTransaction(); diff --git a/Server/mods/deathmatch/logic/CResourceManager.cpp b/Server/mods/deathmatch/logic/CResourceManager.cpp index 801fbe6081b..44ff0b5beed 100644 --- a/Server/mods/deathmatch/logic/CResourceManager.cpp +++ b/Server/mods/deathmatch/logic/CResourceManager.cpp @@ -747,6 +747,8 @@ void CResourceManager::QueueResource(CResource* pResource, eResourceQueue eQueue void CResourceManager::ProcessQueue() { + CPerformanceRecorder::Sample sample("CResourceManager::ProcessQueue"); + sample.SetArg("Queue size", m_resourceQueue.size()); // While we have queuestuff to process while (m_resourceQueue.size() > 0) { diff --git a/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp b/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp index fe6ed2a7b9f..d2cb1beedb6 100644 --- a/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp +++ b/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp @@ -878,12 +878,15 @@ bool CStaticFunctionDefinitions::SetElementData(CElement* pElement, const char* assert(pElement); assert(szName); assert(strlen(szName) <= MAX_CUSTOMDATA_NAME_LENGTH); + CPerformanceRecorder::FunctionSample sample("setElementData"); ESyncType lastSyncType = ESyncType::BROADCAST; CLuaArgument* pCurrentVariable = pElement->GetCustomData(szName, false, &lastSyncType); if (!pCurrentVariable || *pCurrentVariable != Variable || lastSyncType != syncType) { + sample.SetArg("Sync type", EnumToString(syncType)); + sample.SetArg("Key", szName); if (syncType != ESyncType::LOCAL) { // Tell our clients to update their data @@ -893,6 +896,7 @@ bool CStaticFunctionDefinitions::SetElementData(CElement* pElement, const char* BitStream.pBitStream->Write(szName, usNameLength); Variable.WriteToBitStream(*BitStream.pBitStream); + CPerformanceRecorder::Sample sample("Broadcast"); if (syncType == ESyncType::BROADCAST) m_pPlayerManager->BroadcastOnlyJoined(CElementRPCPacket(pElement, SET_ELEMENT_DATA, *BitStream.pBitStream)); else diff --git a/Server/mods/deathmatch/logic/CUnoccupiedVehicleSync.cpp b/Server/mods/deathmatch/logic/CUnoccupiedVehicleSync.cpp index 7da1c780c8c..235d67432bb 100644 --- a/Server/mods/deathmatch/logic/CUnoccupiedVehicleSync.cpp +++ b/Server/mods/deathmatch/logic/CUnoccupiedVehicleSync.cpp @@ -19,6 +19,7 @@ CUnoccupiedVehicleSync::CUnoccupiedVehicleSync(CPlayerManager* pPlayerManager, C void CUnoccupiedVehicleSync::DoPulse() { + CPerformanceRecorder::Sample sample("CUnoccupiedVehicleSync::DoPulse"); // Time to check for players that should no longer be syncing a vehicle or vehicles that should be synced? if (m_UpdateTimer.Get() > 500) { diff --git a/Server/mods/deathmatch/logic/lua/CLuaManager.cpp b/Server/mods/deathmatch/logic/lua/CLuaManager.cpp index b5b660ee2c4..b63e54b0620 100644 --- a/Server/mods/deathmatch/logic/lua/CLuaManager.cpp +++ b/Server/mods/deathmatch/logic/lua/CLuaManager.cpp @@ -104,12 +104,14 @@ void CLuaManager::OnLuaMainCloseVM(CLuaMain* pLuaMain, lua_State* luaVM) void CLuaManager::DoPulse() { + CPerformanceRecorder::Sample sample("CLuaManager::DoPulse"); list::iterator iter; for (iter = m_virtualMachines.begin(); iter != m_virtualMachines.end(); ++iter) { (*iter)->DoPulse(); } m_pLuaModuleManager->DoPulse(); + sample.SetArg("Virtual machines count", m_virtualMachines.size()); } CLuaMain* CLuaManager::GetVirtualMachine(lua_State* luaVM) diff --git a/Server/mods/deathmatch/logic/lua/CLuaTimerManager.cpp b/Server/mods/deathmatch/logic/lua/CLuaTimerManager.cpp index 4e0aeaacb5a..c90802eeef1 100644 --- a/Server/mods/deathmatch/logic/lua/CLuaTimerManager.cpp +++ b/Server/mods/deathmatch/logic/lua/CLuaTimerManager.cpp @@ -24,6 +24,8 @@ void CLuaTimerManager::DoPulse(CLuaMain* pLuaMain) for (CFastList::const_iterator iter = m_TimerList.begin(); iter != m_TimerList.end(); ++iter) m_ProcessQueue.push_back(*iter); + CPerformanceRecorder::Sample sample("CLuaTimerManager::DoPulse"); + int executed = 0; while (!m_ProcessQueue.empty()) { m_pProcessingTimer = m_ProcessQueue.front(); @@ -36,7 +38,12 @@ void CLuaTimerManager::DoPulse(CLuaMain* pLuaMain) // Is the time up and is not being deleted if (llCurrentTime >= (llStartTime + llDelay)) { + executed++; + CPerformanceRecorder::Sample timerSample("Timer executed"); // Set our debug info + const SLuaDebugInfo& debugInfo = m_pProcessingTimer->GetLuaDebugInfo(); + timerSample.SetArg("File",debugInfo.strFile); + timerSample.SetArg("Line",debugInfo.iLine); g_pGame->GetScriptDebugging()->SaveLuaDebugInfo(m_pProcessingTimer->GetLuaDebugInfo()); m_pProcessingTimer->ExecuteTimer(pLuaMain); @@ -69,6 +76,7 @@ void CLuaTimerManager::DoPulse(CLuaMain* pLuaMain) else m_pProcessingTimer = NULL; } + sample.SetArg("Executed timers", executed); } void CLuaTimerManager::RemoveTimer(CLuaTimer* pLuaTimer) diff --git a/Server/mods/deathmatch/utils/CFunctionUseLogger.cpp b/Server/mods/deathmatch/utils/CFunctionUseLogger.cpp index 9cfc6fe4213..71420306edf 100644 --- a/Server/mods/deathmatch/utils/CFunctionUseLogger.cpp +++ b/Server/mods/deathmatch/utils/CFunctionUseLogger.cpp @@ -32,6 +32,7 @@ CFunctionUseLogger::~CFunctionUseLogger() // void CFunctionUseLogger::Pulse() { + CPerformanceRecorder::Sample sample("CFunctionUseLogger::Pulse"); if (!m_FuncCallRecordMap.empty()) MaybeFlush(); } diff --git a/Shared/mods/deathmatch/logic/CLatentTransferManager.cpp b/Shared/mods/deathmatch/logic/CLatentTransferManager.cpp index a9bf07ecb7a..966a8f729bc 100644 --- a/Shared/mods/deathmatch/logic/CLatentTransferManager.cpp +++ b/Shared/mods/deathmatch/logic/CLatentTransferManager.cpp @@ -42,6 +42,7 @@ CLatentTransferManager::~CLatentTransferManager() /////////////////////////////////////////////////////////////// void CLatentTransferManager::DoPulse() { + CPerformanceRecorder::Sample sample("CLatentTransferManager::DoPulse"); // Update timing info CTickCount tickCountNow = CTickCount::Now(); From dd6ab1edf6def3ea28c439b2fcc4f23c73812f99 Mon Sep 17 00:00:00 2001 From: CrosRoad95 Date: Fri, 19 Mar 2021 08:49:09 +0100 Subject: [PATCH 03/10] move recorder to shared logic --- Client/mods/deathmatch/StdInc.h | 1 + Client/mods/deathmatch/logic/CClientGame.cpp | 2 + Client/mods/deathmatch/logic/CClientGame.h | 2 + Client/mods/deathmatch/premake5.lua | 1 + Server/mods/deathmatch/StdInc.h | 2 +- .../logic/CStaticFunctionDefinitions.cpp | 6 +-- .../deathmatch/logic/lua/CLuaTimerManager.cpp | 11 ++-- Server/mods/deathmatch/premake5.lua | 2 + .../deathmatch/logic/luadefs/CLuaUtilDefs.cpp | 51 ++++++++++++++++--- .../deathmatch/logic/luadefs/CLuaUtilDefs.h | 6 ++- Shared/premake5.lua | 1 + .../sdk/profiler}/CPerformanceRecorder.cpp | 47 ++++++++++------- .../sdk/profiler}/CPerformanceRecorder.h | 6 +-- 13 files changed, 102 insertions(+), 36 deletions(-) rename {Server/mods/deathmatch/logic => Shared/sdk/profiler}/CPerformanceRecorder.cpp (69%) rename {Server/mods/deathmatch/logic => Shared/sdk/profiler}/CPerformanceRecorder.h (89%) diff --git a/Client/mods/deathmatch/StdInc.h b/Client/mods/deathmatch/StdInc.h index 143e7a3498d..f5b701f6258 100644 --- a/Client/mods/deathmatch/StdInc.h +++ b/Client/mods/deathmatch/StdInc.h @@ -150,6 +150,7 @@ #include "CLatentTransferManager.h" #include "CDebugHookManager.h" #include "lua/CLuaShared.h" +#include "profiler/CPerformanceRecorder.h" // Deathmatch includes #include "ClientCommands.h" diff --git a/Client/mods/deathmatch/logic/CClientGame.cpp b/Client/mods/deathmatch/logic/CClientGame.cpp index c76142abebf..c926e1c6ee4 100644 --- a/Client/mods/deathmatch/logic/CClientGame.cpp +++ b/Client/mods/deathmatch/logic/CClientGame.cpp @@ -184,6 +184,7 @@ CClientGame::CClientGame(bool bLocalPlay) : m_ServerInfo(new CServerInfo()) m_pScriptKeyBinds = new CScriptKeyBinds; m_pRemoteCalls = new CRemoteCalls(); m_pResourceFileDownloadManager = new CResourceFileDownloadManager(); + m_pPerformanceRecorder = new CPerformanceRecorder(); // Create our net API m_pNetAPI = new CNetAPI(m_pManager); @@ -479,6 +480,7 @@ CClientGame::~CClientGame() SAFE_DELETE(m_pLuaManager); SAFE_DELETE(m_pLatentTransferManager); SAFE_DELETE(m_pResourceFileDownloadManager); + SAFE_DELETE(m_pPerformanceRecorder); SAFE_DELETE(m_pRootEntity); diff --git a/Client/mods/deathmatch/logic/CClientGame.h b/Client/mods/deathmatch/logic/CClientGame.h index 7633479508e..e9d44cc1ecd 100644 --- a/Client/mods/deathmatch/logic/CClientGame.h +++ b/Client/mods/deathmatch/logic/CClientGame.h @@ -299,6 +299,7 @@ class CClientGame CLatentTransferManager* GetLatentTransferManager() { return m_pLatentTransferManager; } CClientModelCacheManager* GetModelCacheManager() { return m_pModelCacheManager; } CDebugHookManager* GetDebugHookManager() { return m_pDebugHookManager; } + CPerformanceRecorder* GetPerformanceRecorder() const { return m_pPerformanceRecorder; } CElementDeleter* GetElementDeleter() { return &m_ElementDeleter; } CObjectRespawner* GetObjectRespawner() { return &m_ObjectRespawner; } @@ -688,6 +689,7 @@ class CClientGame CDebugHookManager* m_pDebugHookManager; CRemoteCalls* m_pRemoteCalls; CResourceFileDownloadManager* m_pResourceFileDownloadManager; + CPerformanceRecorder* m_pPerformanceRecorder; // Revised facilities CServer m_Server; diff --git a/Client/mods/deathmatch/premake5.lua b/Client/mods/deathmatch/premake5.lua index e5bb371fa02..0dc78dbf4f0 100644 --- a/Client/mods/deathmatch/premake5.lua +++ b/Client/mods/deathmatch/premake5.lua @@ -54,6 +54,7 @@ project "Client Deathmatch" "../../../Shared/mods/deathmatch/logic/**.h", "../../../Shared/animation/CEasingCurve.cpp", "../../../Shared/animation/CPositionRotationAnimation.cpp", + "../../../Shared/sdk/profiler/CPerformanceRecorder.cpp", -- Todo: Replace these two by using the CryptoPP functions instead "../../../vendor/bochs/bochs_internal/bochs_crc32.cpp" } diff --git a/Server/mods/deathmatch/StdInc.h b/Server/mods/deathmatch/StdInc.h index 949d002056c..01d71dc8e28 100644 --- a/Server/mods/deathmatch/StdInc.h +++ b/Server/mods/deathmatch/StdInc.h @@ -177,7 +177,7 @@ struct SAclRequest; // Logic includes #include "ASE.h" -#include "CPerformanceRecorder.h" +#include "profiler/CPerformanceRecorder.h" #include "ASEQuerySDK.h" #include "CAccessControlList.h" #include "CAccessControlListGroup.h" diff --git a/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp b/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp index d2cb1beedb6..0c15e23611c 100644 --- a/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp +++ b/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp @@ -883,12 +883,13 @@ bool CStaticFunctionDefinitions::SetElementData(CElement* pElement, const char* ESyncType lastSyncType = ESyncType::BROADCAST; CLuaArgument* pCurrentVariable = pElement->GetCustomData(szName, false, &lastSyncType); + sample.SetArg("Sync type", EnumToString(syncType)); + sample.SetArg("Key", szName); if (!pCurrentVariable || *pCurrentVariable != Variable || lastSyncType != syncType) { - sample.SetArg("Sync type", EnumToString(syncType)); - sample.SetArg("Key", szName); if (syncType != ESyncType::LOCAL) { + CPerformanceRecorder::Sample sample("Broadcast"); // Tell our clients to update their data unsigned short usNameLength = static_cast(strlen(szName)); CBitStream BitStream; @@ -896,7 +897,6 @@ bool CStaticFunctionDefinitions::SetElementData(CElement* pElement, const char* BitStream.pBitStream->Write(szName, usNameLength); Variable.WriteToBitStream(*BitStream.pBitStream); - CPerformanceRecorder::Sample sample("Broadcast"); if (syncType == ESyncType::BROADCAST) m_pPlayerManager->BroadcastOnlyJoined(CElementRPCPacket(pElement, SET_ELEMENT_DATA, *BitStream.pBitStream)); else diff --git a/Server/mods/deathmatch/logic/lua/CLuaTimerManager.cpp b/Server/mods/deathmatch/logic/lua/CLuaTimerManager.cpp index c90802eeef1..9416adebce9 100644 --- a/Server/mods/deathmatch/logic/lua/CLuaTimerManager.cpp +++ b/Server/mods/deathmatch/logic/lua/CLuaTimerManager.cpp @@ -16,16 +16,18 @@ void CLuaTimerManager::DoPulse(CLuaMain* pLuaMain) assert(m_ProcessQueue.empty()); assert(!m_pPendingDelete); assert(!m_pProcessingTimer); - CTickCount llCurrentTime = CTickCount::Now(); + CPerformanceRecorder::Sample sample("CLuaTimerManager::DoPulse"); + sample.SetArg("Resource name", pLuaMain->GetResource()->GetName()); // Use a separate queue to avoid trouble // What kind of problems are we trying to avoid? Doing a copy each frame isn't quite efficient for (CFastList::const_iterator iter = m_TimerList.begin(); iter != m_TimerList.end(); ++iter) m_ProcessQueue.push_back(*iter); - CPerformanceRecorder::Sample sample("CLuaTimerManager::DoPulse"); - int executed = 0; + int executed = 0; + int timersCount = m_ProcessQueue.size(); + while (!m_ProcessQueue.empty()) { m_pProcessingTimer = m_ProcessQueue.front(); @@ -44,7 +46,7 @@ void CLuaTimerManager::DoPulse(CLuaMain* pLuaMain) const SLuaDebugInfo& debugInfo = m_pProcessingTimer->GetLuaDebugInfo(); timerSample.SetArg("File",debugInfo.strFile); timerSample.SetArg("Line",debugInfo.iLine); - g_pGame->GetScriptDebugging()->SaveLuaDebugInfo(m_pProcessingTimer->GetLuaDebugInfo()); + g_pGame->GetScriptDebugging()->SaveLuaDebugInfo(debugInfo); m_pProcessingTimer->ExecuteTimer(pLuaMain); // Reset @@ -76,6 +78,7 @@ void CLuaTimerManager::DoPulse(CLuaMain* pLuaMain) else m_pProcessingTimer = NULL; } + sample.SetArg("Timers count", timersCount); sample.SetArg("Executed timers", executed); } diff --git a/Server/mods/deathmatch/premake5.lua b/Server/mods/deathmatch/premake5.lua index 48c3cead82a..5070e3c6a8b 100644 --- a/Server/mods/deathmatch/premake5.lua +++ b/Server/mods/deathmatch/premake5.lua @@ -26,6 +26,7 @@ project "Deathmatch" "../../../Shared/mods/deathmatch/logic", "../../../Shared/animation", "../../../Shared/publicsdk/include", + "../../../Shared/sdk/profiler", "../../../vendor/sparsehash/src/", "logic", "utils", @@ -51,6 +52,7 @@ project "Deathmatch" "../../../Shared/mods/deathmatch/logic/**.h", "../../../Shared/animation/CEasingCurve.cpp", "../../../Shared/animation/CPositionRotationAnimation.cpp", + "../../../Shared/sdk/profiler/CPerformanceRecorder.cpp", -- Todo: Replace these two by using the CryptoPP functions instead "../../../vendor/bochs/bochs_internal/bochs_crc32.cpp", } diff --git a/Shared/mods/deathmatch/logic/luadefs/CLuaUtilDefs.cpp b/Shared/mods/deathmatch/logic/luadefs/CLuaUtilDefs.cpp index 9745e6e5f66..53d54444b4b 100644 --- a/Shared/mods/deathmatch/logic/luadefs/CLuaUtilDefs.cpp +++ b/Shared/mods/deathmatch/logic/luadefs/CLuaUtilDefs.cpp @@ -9,6 +9,7 @@ *****************************************************************************/ #include "StdInc.h" +#include void CLuaUtilDefs::LoadFunctions() { @@ -46,9 +47,13 @@ void CLuaUtilDefs::LoadFunctions() // Utility functions {"gettok", GetTok}, {"tocolor", tocolor}, + + // Performance recorder {"startRecordPerformance", ArgumentParser}, {"stopRecordPerformance", ArgumentParser}, - {"getRecordedPerformance", ArgumentParser}, + {"clearPerformanceRecorder", ArgumentParser}, + {"isPerformanceRecording", ArgumentParser}, + {"getRecordedSamples", ArgumentParser}, }; // Add functions @@ -715,29 +720,63 @@ int CLuaUtilDefs::tocolor(lua_State* luaVM) return 1; } -bool CLuaUtilDefs::StartRecordPerformance(std::optional bClear) +bool CLuaUtilDefs::StartRecordPerformance() { +#ifdef MTA_CLIENT + if (g_pClientGame->GetPerformanceRecorder()->IsDuringPerformanceRecording()) + return false; + + g_pClientGame->GetPerformanceRecorder()->Start(); +#else if (g_pGame->GetPerformanceRecorder()->IsDuringPerformanceRecording()) return false; g_pGame->GetPerformanceRecorder()->Start(); - - if (bClear.value_or(false)) - g_pGame->GetPerformanceRecorder()->Clear(); +#endif return true; } bool CLuaUtilDefs::StopRecordPerformance() { +#ifdef MTA_CLIENT + if (!g_pClientGame->GetPerformanceRecorder()->IsDuringPerformanceRecording()) + return false; + + g_pClientGame->GetPerformanceRecorder()->Stop(); +#else if (!g_pGame->GetPerformanceRecorder()->IsDuringPerformanceRecording()) return false; g_pGame->GetPerformanceRecorder()->Stop(); +#endif + return true; +} + +bool CLuaUtilDefs::ClearPerformanceRecorder() +{ +#ifdef MTA_CLIENT + g_pClientGame->GetPerformanceRecorder()->Clear(); +#else + g_pGame->GetPerformanceRecorder()->Clear(); +#endif return true; } -std::string CLuaUtilDefs::GetRecordedPerformance() +bool CLuaUtilDefs::IsPerformanceRecording() +{ +#ifdef MTA_CLIENT + return g_pClientGame->GetPerformanceRecorder()->IsDuringPerformanceRecording(); +#else + return g_pGame->GetPerformanceRecorder()->IsDuringPerformanceRecording(); +#endif +} + +std::string CLuaUtilDefs::GetRecordedSamples() { +#ifdef MTA_CLIENT + return g_pClientGame->GetPerformanceRecorder()->GetResult(); +#else return g_pGame->GetPerformanceRecorder()->GetResult(); +#endif } diff --git a/Shared/mods/deathmatch/logic/luadefs/CLuaUtilDefs.h b/Shared/mods/deathmatch/logic/luadefs/CLuaUtilDefs.h index 3d0f76f987a..fa3a9ad2ae4 100644 --- a/Shared/mods/deathmatch/logic/luadefs/CLuaUtilDefs.h +++ b/Shared/mods/deathmatch/logic/luadefs/CLuaUtilDefs.h @@ -53,7 +53,9 @@ class CLuaUtilDefs : public CLuaDefs LUA_DECLARE(GetTok); LUA_DECLARE(tocolor); - static bool StartRecordPerformance(std::optional bClear); + static bool StartRecordPerformance(); static bool StopRecordPerformance(); - static std::string GetRecordedPerformance(); + static bool ClearPerformanceRecorder(); + static bool IsPerformanceRecording(); + static std::string GetRecordedSamples(); }; diff --git a/Shared/premake5.lua b/Shared/premake5.lua index 76c3c52c84a..309e24907ac 100644 --- a/Shared/premake5.lua +++ b/Shared/premake5.lua @@ -10,6 +10,7 @@ project "Shared" vpaths { ["Headers/*"] = { "**.h", "**.hpp" }, + ["Sources/*"] = "**.cpp", ["*"] = "premake5.lua", } diff --git a/Server/mods/deathmatch/logic/CPerformanceRecorder.cpp b/Shared/sdk/profiler/CPerformanceRecorder.cpp similarity index 69% rename from Server/mods/deathmatch/logic/CPerformanceRecorder.cpp rename to Shared/sdk/profiler/CPerformanceRecorder.cpp index 29c931359e7..89c4c3e2524 100644 --- a/Server/mods/deathmatch/logic/CPerformanceRecorder.cpp +++ b/Shared/sdk/profiler/CPerformanceRecorder.cpp @@ -11,7 +11,12 @@ CPerformanceRecorder::~CPerformanceRecorder() void CPerformanceRecorder::Start() { m_bRecordPerformance = true; - g_pGame->GetPerformanceRecorder()->m_strStream << '['; +#ifdef MTA_CLIENT + g_pClientGame->GetPerformanceRecorder()->m_strStream +#else + g_pGame->GetPerformanceRecorder()->m_strStream +#endif + << '['; } void CPerformanceRecorder::Stop() @@ -32,24 +37,25 @@ std::string CPerformanceRecorder::GetResult() CPerformanceRecorder::FunctionSample::FunctionSample(const char* name) : Sample("") { - m_szName = std::string("Native function: ") + name; - m_szCategory = "function"; + m_name = std::string("Native function: ") + name; + m_category = "function"; } CPerformanceRecorder::EventSample::EventSample(const char* name) : Sample("") { - m_szName = std::string("Event: ") + name; - m_szCategory = "event"; + m_name = std::string("Event: ") + name; + m_category = "event"; } -CPerformanceRecorder::Sample::Sample(const char* name) : m_szName(name), m_start(GetTimeUs()) +CPerformanceRecorder::Sample::Sample(const char* name) : m_name(name), m_startTime(GetTimeUs()) { - if (g_pGame->GetPerformanceRecorder() ->m_bRecordPerformance) +#ifdef MTA_CLIENT + if (g_pClientGame->GetPerformanceRecorder()->m_bRecordPerformance) +#else + if (g_pGame->GetPerformanceRecorder()->m_bRecordPerformance) +#endif m_pObject = json_object_new_object(); } -// -//{"name": "aaaaaaaaaaa", "cat": "PERF", "ph": "B", "pid": 22630, "tid": 22630, "ts": 829, "cname": "foo"}, -//{"name": "aaaaaaaaaaa", "cat": "PERF", "ph": "E", "pid": 22630, "tid": 22630, "ts": 2000, "cname": "foo"}, void CPerformanceRecorder::Sample::SetArg(const char* szKey, const char* value) { @@ -72,17 +78,18 @@ CPerformanceRecorder::Sample::~Sample() if (m_pObject) { json_object* m_pObjectStart = json_object_new_object(); - json_object_object_add(m_pObjectStart, "name", json_object_new_string(m_szName.c_str())); - json_object_object_add(m_pObjectStart, "cat", json_object_new_string(m_szCategory)); + json_object_object_add(m_pObjectStart, "name", json_object_new_string(m_name.c_str())); + json_object_object_add(m_pObjectStart, "cat", json_object_new_string(m_category.c_str())); json_object_object_add(m_pObjectStart, "ph", json_object_new_string("B")); - json_object_object_add(m_pObjectStart, "ts", json_object_new_int(m_start)); + json_object_object_add(m_pObjectStart, "ts", json_object_new_int(m_startTime)); json_object_object_add(m_pObjectStart, "pid", json_object_new_int(GetCurrentThreadId())); - json_object_object_add(m_pObject, "name", json_object_new_string(m_szName.c_str())); - json_object_object_add(m_pObject, "cat", json_object_new_string(m_szCategory)); + json_object_object_add(m_pObject, "name", json_object_new_string(m_name.c_str())); + json_object_object_add(m_pObject, "cat", json_object_new_string(m_category.c_str())); json_object_object_add(m_pObject, "ph", json_object_new_string("E")); json_object_object_add(m_pObject, "ts", json_object_new_int(GetTimeUs())); json_object_object_add(m_pObject, "pid", json_object_new_int(GetCurrentThreadId())); + if (m_pObjectArgs) { json_object_object_add(m_pObjectStart, "args", m_pObjectArgs); @@ -90,8 +97,14 @@ CPerformanceRecorder::Sample::~Sample() int flags = JSON_C_TO_STRING_PLAIN; - g_pGame->GetPerformanceRecorder()->m_strStream << json_object_to_json_string_ext(m_pObjectStart, flags) << ','; - g_pGame->GetPerformanceRecorder()->m_strStream << json_object_to_json_string_ext(m_pObject, flags) << ','; +#ifdef MTA_CLIENT + g_pClientGame->GetPerformanceRecorder()->m_strStream +#else + g_pGame->GetPerformanceRecorder()->m_strStream +#endif + << json_object_to_json_string_ext(m_pObjectStart, flags) << ',' + << json_object_to_json_string_ext(m_pObject, flags) << ','; + json_object_put(m_pObject); json_object_put(m_pObjectStart); } diff --git a/Server/mods/deathmatch/logic/CPerformanceRecorder.h b/Shared/sdk/profiler/CPerformanceRecorder.h similarity index 89% rename from Server/mods/deathmatch/logic/CPerformanceRecorder.h rename to Shared/sdk/profiler/CPerformanceRecorder.h index a1748156637..df97fd0d1b6 100644 --- a/Server/mods/deathmatch/logic/CPerformanceRecorder.h +++ b/Shared/sdk/profiler/CPerformanceRecorder.h @@ -23,10 +23,10 @@ class CPerformanceRecorder void SetArg(const char* szKey, int value); protected: - std::string m_szName; - const char* m_szCategory = "default"; + std::string m_name; + std::string m_category = "default"; private: - TIMEUS m_start = 0; + TIMEUS m_startTime = 0; json_object* m_pObject = nullptr; json_object* m_pObjectArgs = nullptr; }; From a8c95292d6f6a2fd257a9c0c6024b30feceb40c9 Mon Sep 17 00:00:00 2001 From: CrosRoad95 Date: Fri, 19 Mar 2021 08:55:21 +0100 Subject: [PATCH 04/10] fix compilation maybe --- Shared/sdk/profiler/CPerformanceRecorder.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Shared/sdk/profiler/CPerformanceRecorder.h b/Shared/sdk/profiler/CPerformanceRecorder.h index df97fd0d1b6..2ba869cf04c 100644 --- a/Shared/sdk/profiler/CPerformanceRecorder.h +++ b/Shared/sdk/profiler/CPerformanceRecorder.h @@ -1,3 +1,5 @@ +#pragma once + class CPerformanceRecorder { friend class Sample; From 4c8917e372cb86e6e11ffa5a83b3896211b03df0 Mon Sep 17 00:00:00 2001 From: CrosRoad95 Date: Fri, 19 Mar 2021 09:06:47 +0100 Subject: [PATCH 05/10] fix compilation --- Shared/sdk/profiler/CPerformanceRecorder.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Shared/sdk/profiler/CPerformanceRecorder.cpp b/Shared/sdk/profiler/CPerformanceRecorder.cpp index 89c4c3e2524..08fd2fd2cce 100644 --- a/Shared/sdk/profiler/CPerformanceRecorder.cpp +++ b/Shared/sdk/profiler/CPerformanceRecorder.cpp @@ -82,13 +82,13 @@ CPerformanceRecorder::Sample::~Sample() json_object_object_add(m_pObjectStart, "cat", json_object_new_string(m_category.c_str())); json_object_object_add(m_pObjectStart, "ph", json_object_new_string("B")); json_object_object_add(m_pObjectStart, "ts", json_object_new_int(m_startTime)); - json_object_object_add(m_pObjectStart, "pid", json_object_new_int(GetCurrentThreadId())); + json_object_object_add(m_pObjectStart, "pid", json_object_new_int(0)); json_object_object_add(m_pObject, "name", json_object_new_string(m_name.c_str())); json_object_object_add(m_pObject, "cat", json_object_new_string(m_category.c_str())); json_object_object_add(m_pObject, "ph", json_object_new_string("E")); json_object_object_add(m_pObject, "ts", json_object_new_int(GetTimeUs())); - json_object_object_add(m_pObject, "pid", json_object_new_int(GetCurrentThreadId())); + json_object_object_add(m_pObject, "pid", json_object_new_int(0)); if (m_pObjectArgs) { From 8d9c0b98a9b5d0b669feaa596b04d8352a33a941 Mon Sep 17 00:00:00 2001 From: CrosRoad95 Date: Sat, 20 Mar 2021 13:36:32 +0100 Subject: [PATCH 06/10] add missing samples, refactor --- Server/mods/deathmatch/logic/CGame.cpp | 6 + .../mods/deathmatch/logic/net/CNetBuffer.cpp | 1 + Shared/sdk/profiler/CPerformanceRecorder.cpp | 151 ++++++++++++------ Shared/sdk/profiler/CPerformanceRecorder.h | 31 ++-- 4 files changed, 126 insertions(+), 63 deletions(-) diff --git a/Server/mods/deathmatch/logic/CGame.cpp b/Server/mods/deathmatch/logic/CGame.cpp index a85cc7a9e18..75dc93d612d 100644 --- a/Server/mods/deathmatch/logic/CGame.cpp +++ b/Server/mods/deathmatch/logic/CGame.cpp @@ -473,10 +473,16 @@ void CGame::DoPulse() CLOCK_CALL1(CPerfStatManager::GetSingleton()->DoPulse();); if (m_pMasterServerAnnouncer) + { + CPerformanceRecorder::Sample sample("CMasterServerAnnouncer::Pulse"); m_pMasterServerAnnouncer->Pulse(); + } if (m_pHqComms) + { + CPerformanceRecorder::Sample sample("CHqComms::Pulse"); m_pHqComms->Pulse(); + } CLOCK_CALL1(m_pFunctionUseLogger->Pulse();); CLOCK_CALL1(m_lightsyncManager.DoPulse();); diff --git a/Server/mods/deathmatch/logic/net/CNetBuffer.cpp b/Server/mods/deathmatch/logic/net/CNetBuffer.cpp index b2c9f20aad1..ca05fed0cf6 100644 --- a/Server/mods/deathmatch/logic/net/CNetBuffer.cpp +++ b/Server/mods/deathmatch/logic/net/CNetBuffer.cpp @@ -220,6 +220,7 @@ void CNetServerBuffer::StopNetwork() /////////////////////////////////////////////////////////////////////////// void CNetServerBuffer::DoPulse() { + CPerformanceRecorder::Sample sample("CNetServerBuffer::DoPulse"); // Schedule a net pulse SDoPulseArgs* pArgs = new SDoPulseArgs(); AddCommandAndFree(pArgs); diff --git a/Shared/sdk/profiler/CPerformanceRecorder.cpp b/Shared/sdk/profiler/CPerformanceRecorder.cpp index 08fd2fd2cce..b2ba586c94b 100644 --- a/Shared/sdk/profiler/CPerformanceRecorder.cpp +++ b/Shared/sdk/profiler/CPerformanceRecorder.cpp @@ -2,6 +2,7 @@ CPerformanceRecorder::CPerformanceRecorder() { + m_samples = json_object_new_array(); } CPerformanceRecorder::~CPerformanceRecorder() @@ -11,12 +12,6 @@ CPerformanceRecorder::~CPerformanceRecorder() void CPerformanceRecorder::Start() { m_bRecordPerformance = true; -#ifdef MTA_CLIENT - g_pClientGame->GetPerformanceRecorder()->m_strStream -#else - g_pGame->GetPerformanceRecorder()->m_strStream -#endif - << '['; } void CPerformanceRecorder::Stop() @@ -26,86 +21,140 @@ void CPerformanceRecorder::Stop() void CPerformanceRecorder::Clear() { - m_strStream.clear(); + // m_strStream.clear(); m_start = GetTimeUs(); } +void CPerformanceRecorder::EnterScope() +{ + m_stackSamples.push(json_object_new_object()); +} + +void CPerformanceRecorder::ExitScope() +{ + assert(m_stackSamples.size() > 0); + json_object* top = m_stackSamples.top(); + json_object_array_add(m_samples, m_stackSamples.top()); + m_stackSamples.pop(); +} + +json_object* CPerformanceRecorder::GetSampleObject() +{ + assert(m_stackSamples.size() > 0); + return m_stackSamples.top(); +} + std::string CPerformanceRecorder::GetResult() { - return m_strStream.str() + "]"; + int flags = JSON_C_TO_STRING_PLAIN; + return json_object_to_json_string_ext(m_samples, flags); } -CPerformanceRecorder::FunctionSample::FunctionSample(const char* name) : Sample("") +CPerformanceRecorder::FunctionSample::FunctionSample(const char* name) : Sample(name) { - m_name = std::string("Native function: ") + name; - m_category = "function"; } -CPerformanceRecorder::EventSample::EventSample(const char* name) : Sample("") +CPerformanceRecorder::FunctionSample::~FunctionSample() { - m_name = std::string("Event: ") + name; - m_category = "event"; +#ifdef MTA_CLIENT + json_object* object = g_pClientGame->GetPerformanceRecorder()->GetSampleObject(); +#else + json_object* object = g_pGame->GetPerformanceRecorder()->GetSampleObject(); +#endif + json_object_object_add(object, "name", json_object_new_string(("Native function: " + m_name).c_str())); + json_object_object_add(object, "cat", json_object_new_string("function")); +} + +CPerformanceRecorder::EventSample::EventSample(const char* name) : Sample(name) +{ +} + +CPerformanceRecorder::EventSample::~EventSample() +{ +#ifdef MTA_CLIENT + json_object* object = g_pClientGame->GetPerformanceRecorder()->GetSampleObject(); +#else + json_object* object = g_pGame->GetPerformanceRecorder()->GetSampleObject(); +#endif + json_object_object_add(object, "name", json_object_new_string(("Event: " + m_name).c_str())); + json_object_object_add(object, "cat", json_object_new_string("event")); } CPerformanceRecorder::Sample::Sample(const char* name) : m_name(name), m_startTime(GetTimeUs()) { #ifdef MTA_CLIENT - if (g_pClientGame->GetPerformanceRecorder()->m_bRecordPerformance) + m_enabled = g_pClientGame->GetPerformanceRecorder()->m_bRecordPerformance; + g_pClientGame->GetPerformanceRecorder()->EnterScope(); #else - if (g_pGame->GetPerformanceRecorder()->m_bRecordPerformance) + m_enabled = g_pGame->GetPerformanceRecorder()->m_bRecordPerformance; + g_pGame->GetPerformanceRecorder()->EnterScope(); #endif - m_pObject = json_object_new_object(); } void CPerformanceRecorder::Sample::SetArg(const char* szKey, const char* value) { - if (!m_pObjectArgs) - m_pObjectArgs = json_object_new_object(); + if (!m_enabled) + return; - json_object_object_add(m_pObjectArgs, szKey, json_object_new_string(value)); +#ifdef MTA_CLIENT + json_object* object = g_pClientGame->GetPerformanceRecorder()->GetSampleObject(); +#else + json_object* object = g_pGame->GetPerformanceRecorder()->GetSampleObject(); +#endif + json_object* args = json_object_object_get(object, "args"); + if (!args) + { + args = json_object_new_object(); + json_object_object_add(object, "args", args); + } + + json_object_object_add(args, szKey, json_object_new_string(value)); } void CPerformanceRecorder::Sample::SetArg(const char* szKey, int value) { - if (!m_pObjectArgs) - m_pObjectArgs = json_object_new_object(); + if (!m_enabled) + return; - json_object_object_add(m_pObjectArgs, szKey, json_object_new_int(value)); +#ifdef MTA_CLIENT + json_object* object = g_pClientGame->GetPerformanceRecorder()->GetSampleObject(); +#else + json_object* object = g_pGame->GetPerformanceRecorder()->GetSampleObject(); +#endif + json_object* args = json_object_object_get(object, "args"); + if (!args) + { + args = json_object_new_object(); + json_object_object_add(object, "args", args); + } + + json_object_object_add(args, szKey, json_object_new_int(value)); } CPerformanceRecorder::Sample::~Sample() { - if (m_pObject) - { - json_object* m_pObjectStart = json_object_new_object(); - json_object_object_add(m_pObjectStart, "name", json_object_new_string(m_name.c_str())); - json_object_object_add(m_pObjectStart, "cat", json_object_new_string(m_category.c_str())); - json_object_object_add(m_pObjectStart, "ph", json_object_new_string("B")); - json_object_object_add(m_pObjectStart, "ts", json_object_new_int(m_startTime)); - json_object_object_add(m_pObjectStart, "pid", json_object_new_int(0)); - - json_object_object_add(m_pObject, "name", json_object_new_string(m_name.c_str())); - json_object_object_add(m_pObject, "cat", json_object_new_string(m_category.c_str())); - json_object_object_add(m_pObject, "ph", json_object_new_string("E")); - json_object_object_add(m_pObject, "ts", json_object_new_int(GetTimeUs())); - json_object_object_add(m_pObject, "pid", json_object_new_int(0)); - - if (m_pObjectArgs) - { - json_object_object_add(m_pObjectStart, "args", m_pObjectArgs); - } - - int flags = JSON_C_TO_STRING_PLAIN; + if (!m_enabled) + return; #ifdef MTA_CLIENT - g_pClientGame->GetPerformanceRecorder()->m_strStream + json_object* object = g_pClientGame->GetPerformanceRecorder()->GetSampleObject(); #else - g_pGame->GetPerformanceRecorder()->m_strStream + json_object* object = g_pGame->GetPerformanceRecorder()->GetSampleObject(); #endif - << json_object_to_json_string_ext(m_pObjectStart, flags) << ',' - << json_object_to_json_string_ext(m_pObject, flags) << ','; - json_object_put(m_pObject); - json_object_put(m_pObjectStart); - } + if (!json_object_object_get(object, "name")) + json_object_object_add(object, "name", json_object_new_string(m_name.c_str())); + if (!json_object_object_get(object, "cat")) + json_object_object_add(object, "cat", json_object_new_string("default")); + + json_object_object_add(object, "ph", json_object_new_string("X")); + json_object_object_add(object, "ts", json_object_new_int(m_startTime)); + json_object_object_add(object, "dur", json_object_new_int(GetTimeUs() - m_startTime)); + json_object_object_add(object, "tid", json_object_new_int(getpid())); + +#ifdef MTA_CLIENT + g_pClientGame->GetPerformanceRecorder()->ExitScope(); +#else + g_pGame->GetPerformanceRecorder()->ExitScope(); +#endif } diff --git a/Shared/sdk/profiler/CPerformanceRecorder.h b/Shared/sdk/profiler/CPerformanceRecorder.h index 2ba869cf04c..f376bcd9cf6 100644 --- a/Shared/sdk/profiler/CPerformanceRecorder.h +++ b/Shared/sdk/profiler/CPerformanceRecorder.h @@ -1,5 +1,7 @@ #pragma once +#include + class CPerformanceRecorder { friend class Sample; @@ -8,46 +10,51 @@ class CPerformanceRecorder CPerformanceRecorder(); ~CPerformanceRecorder(); - void Start(); - void Stop(); - void Clear(); + void Start(); + void Stop(); + void Clear(); + void EnterScope(); + void ExitScope(); + json_object* GetSampleObject(); - bool IsDuringPerformanceRecording() const { return m_bRecordPerformance; } + bool IsDuringPerformanceRecording() const { return m_bRecordPerformance; } std::string GetResult(); class Sample { public: Sample(const char* name); - ~Sample(); + virtual ~Sample(); void SetArg(const char* szKey, const char* value); void SetArg(const char* szKey, int value); protected: std::string m_name; - std::string m_category = "default"; + bool m_enabled; + private: - TIMEUS m_startTime = 0; - json_object* m_pObject = nullptr; - json_object* m_pObjectArgs = nullptr; + TIMEUS m_startTime = 0; }; class FunctionSample : public Sample { public: FunctionSample(const char* name); + ~FunctionSample(); }; - + class EventSample : public Sample { public: EventSample(const char* name); + ~EventSample(); }; private: - bool m_bRecordPerformance = false; + bool m_bRecordPerformance = false; TIMEUS m_start; - std::stringstream m_strStream; + std::stack m_stackSamples; + json_object* m_samples; }; From 9ddd39c86ef9cf39ca74d2c100dcd8cd893ba6c3 Mon Sep 17 00:00:00 2001 From: CrosRoad95 Date: Sat, 20 Mar 2021 14:45:55 +0100 Subject: [PATCH 07/10] fixes --- Shared/sdk/profiler/CPerformanceRecorder.cpp | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/Shared/sdk/profiler/CPerformanceRecorder.cpp b/Shared/sdk/profiler/CPerformanceRecorder.cpp index b2ba586c94b..57a4242de0d 100644 --- a/Shared/sdk/profiler/CPerformanceRecorder.cpp +++ b/Shared/sdk/profiler/CPerformanceRecorder.cpp @@ -1,12 +1,12 @@ #include "StdInc.h" -CPerformanceRecorder::CPerformanceRecorder() +CPerformanceRecorder::CPerformanceRecorder() : m_start(GetTimeUs()), m_samples(json_object_new_array()) { - m_samples = json_object_new_array(); } CPerformanceRecorder::~CPerformanceRecorder() { + json_object_put(m_samples); } void CPerformanceRecorder::Start() @@ -21,8 +21,9 @@ void CPerformanceRecorder::Stop() void CPerformanceRecorder::Clear() { - // m_strStream.clear(); m_start = GetTimeUs(); + json_object_put(m_samples); + m_samples = json_object_new_array(); } void CPerformanceRecorder::EnterScope() @@ -33,7 +34,6 @@ void CPerformanceRecorder::EnterScope() void CPerformanceRecorder::ExitScope() { assert(m_stackSamples.size() > 0); - json_object* top = m_stackSamples.top(); json_object_array_add(m_samples, m_stackSamples.top()); m_stackSamples.pop(); } @@ -56,6 +56,9 @@ CPerformanceRecorder::FunctionSample::FunctionSample(const char* name) : Sample( CPerformanceRecorder::FunctionSample::~FunctionSample() { + if (!m_enabled) + return; + #ifdef MTA_CLIENT json_object* object = g_pClientGame->GetPerformanceRecorder()->GetSampleObject(); #else @@ -71,6 +74,9 @@ CPerformanceRecorder::EventSample::EventSample(const char* name) : Sample(name) CPerformanceRecorder::EventSample::~EventSample() { + if (!m_enabled) + return; + #ifdef MTA_CLIENT json_object* object = g_pClientGame->GetPerformanceRecorder()->GetSampleObject(); #else @@ -84,10 +90,12 @@ CPerformanceRecorder::Sample::Sample(const char* name) : m_name(name), m_startTi { #ifdef MTA_CLIENT m_enabled = g_pClientGame->GetPerformanceRecorder()->m_bRecordPerformance; - g_pClientGame->GetPerformanceRecorder()->EnterScope(); + if (m_enabled) + g_pClientGame->GetPerformanceRecorder()->EnterScope(); #else m_enabled = g_pGame->GetPerformanceRecorder()->m_bRecordPerformance; - g_pGame->GetPerformanceRecorder()->EnterScope(); + if (m_enabled) + g_pGame->GetPerformanceRecorder()->EnterScope(); #endif } From 23e3d8197785d951bec85c3ec34558336a6a713d Mon Sep 17 00:00:00 2001 From: CrosRoad95 Date: Sat, 20 Mar 2021 16:53:21 +0100 Subject: [PATCH 08/10] fix int overflow --- Shared/sdk/profiler/CPerformanceRecorder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Shared/sdk/profiler/CPerformanceRecorder.cpp b/Shared/sdk/profiler/CPerformanceRecorder.cpp index 57a4242de0d..d0936e20276 100644 --- a/Shared/sdk/profiler/CPerformanceRecorder.cpp +++ b/Shared/sdk/profiler/CPerformanceRecorder.cpp @@ -156,7 +156,7 @@ CPerformanceRecorder::Sample::~Sample() json_object_object_add(object, "cat", json_object_new_string("default")); json_object_object_add(object, "ph", json_object_new_string("X")); - json_object_object_add(object, "ts", json_object_new_int(m_startTime)); + json_object_object_add(object, "ts", json_object_new_int64(m_startTime)); // int64 prevents int32 overflowing in this case. json_object_object_add(object, "dur", json_object_new_int(GetTimeUs() - m_startTime)); json_object_object_add(object, "tid", json_object_new_int(getpid())); From b8910b9371a08a7baffb4a4a9a4fffe2ca9d490e Mon Sep 17 00:00:00 2001 From: CrosRoad95 Date: Sun, 21 Mar 2021 08:22:51 +0100 Subject: [PATCH 09/10] clientside samples, exit function, size_t argument --- .../mods/deathmatch/logic/CClientEntity.cpp | 1 + Client/mods/deathmatch/logic/CClientGame.cpp | 15 ++++-- .../logic/CClientModelCacheManager.cpp | 1 + .../mods/deathmatch/logic/CElementDeleter.cpp | 1 + .../logic/CMovingObjectsManager.cpp | 1 + Client/mods/deathmatch/logic/CPedSync.cpp | 1 + .../logic/CUnoccupiedVehicleSync.cpp | 1 + Client/mods/deathmatch/logic/lua/CLuaMain.cpp | 1 + .../mods/deathmatch/logic/lua/CLuaManager.cpp | 2 + .../logic/luadefs/CLuaElementDefs.cpp | 4 +- Server/mods/deathmatch/logic/CGame.cpp | 13 +++-- .../logic/CStaticFunctionDefinitions.cpp | 3 -- .../logic/luadefs/CLuaElementDefs.cpp | 3 ++ Shared/sdk/profiler/CPerformanceRecorder.cpp | 50 ++++++++++++++++++- Shared/sdk/profiler/CPerformanceRecorder.h | 4 ++ 15 files changed, 87 insertions(+), 14 deletions(-) diff --git a/Client/mods/deathmatch/logic/CClientEntity.cpp b/Client/mods/deathmatch/logic/CClientEntity.cpp index 61be4ca269d..36052806c69 100644 --- a/Client/mods/deathmatch/logic/CClientEntity.cpp +++ b/Client/mods/deathmatch/logic/CClientEntity.cpp @@ -732,6 +732,7 @@ bool CClientEntity::AddEvent(CLuaMain* pLuaMain, const char* szName, const CLuaF bool CClientEntity::CallEvent(const char* szName, const CLuaArguments& Arguments, bool bCallOnChildren) { + CPerformanceRecorder::EventSample sample(szName); if (!g_pClientGame->GetDebugHookManager()->OnPreEvent(szName, Arguments, this, NULL)) return false; diff --git a/Client/mods/deathmatch/logic/CClientGame.cpp b/Client/mods/deathmatch/logic/CClientGame.cpp index 5bbd8b22d3f..214606fd736 100644 --- a/Client/mods/deathmatch/logic/CClientGame.cpp +++ b/Client/mods/deathmatch/logic/CClientGame.cpp @@ -733,6 +733,7 @@ void CClientGame::DoPulsePreFrame() void CClientGame::DoPulsePreHUDRender(bool bDidUnminimize, bool bDidRecreateRenderTargets) { + CPerformanceRecorder::Sample sample("CClientGame::DoPulsePreHUDRender"); // Allow scripted dxSetRenderTarget for old scripts g_pCore->GetGraphics()->GetRenderItemManager()->EnableSetRenderTargetOldVer(true); @@ -765,6 +766,7 @@ void CClientGame::DoPulsePreHUDRender(bool bDidUnminimize, bool bDidRecreateRend void CClientGame::DoPulsePostFrame() { + CPerformanceRecorder::Sample sample("CClientGame::DoPulsePostFrame"); TIMING_CHECKPOINT("+CClientGame::DoPulsePostFrame"); #ifdef DEBUG_KEYSTATES // Get the controller state @@ -942,6 +944,7 @@ void CClientGame::DoPulses() g_pCore->ApplyFrameRateLimit(); + CPerformanceRecorder::Sample sample("CClientGame::DoPulses"); TIMING_CHECKPOINT("+CClientGame::DoPulses"); m_BuiltCollisionMapThisFrame = false; @@ -1315,6 +1318,7 @@ void CClientGame::DoPulses() // Extrapolation test void CClientGame::DoPulses2(bool bCalledFromIdle) { + CPerformanceRecorder::Sample sample("CClientGame::DoPulses2"); bool bIsUsingAlternatePulseOrder = IsUsingAlternatePulseOrder(!bCalledFromIdle); // Figure out which pulses to do @@ -1345,11 +1349,12 @@ void CClientGame::DoPulses2(bool bCalledFromIdle) // be rounded to look more like what is expected ChangeFloatPrecision(true); - // Pulse the network interface - TIMING_CHECKPOINT("+NetPulse"); - g_pNet->DoPulse(); - TIMING_CHECKPOINT("-NetPulse"); - + { + // Pulse the network interface + TIMING_CHECKPOINT("+NetPulse"); + g_pNet->DoPulse(); + TIMING_CHECKPOINT("-NetPulse"); + } // Change precision back, and check we are in low precision mode 4 sure ChangeFloatPrecision(false); assert(!IsHighFloatPrecision()); diff --git a/Client/mods/deathmatch/logic/CClientModelCacheManager.cpp b/Client/mods/deathmatch/logic/CClientModelCacheManager.cpp index 42c84cf0c68..4d32f31773a 100644 --- a/Client/mods/deathmatch/logic/CClientModelCacheManager.cpp +++ b/Client/mods/deathmatch/logic/CClientModelCacheManager.cpp @@ -101,6 +101,7 @@ CClientModelCacheManagerImpl::~CClientModelCacheManagerImpl() /////////////////////////////////////////////////////////////// void CClientModelCacheManagerImpl::DoPulse() { + CPerformanceRecorder::Sample sample("CClientModelCacheManager::DoPulse"); m_TickCountNow = CTickCount::Now(); ClearStats(); diff --git a/Client/mods/deathmatch/logic/CElementDeleter.cpp b/Client/mods/deathmatch/logic/CElementDeleter.cpp index 147fa4835a2..44dc6fbd109 100644 --- a/Client/mods/deathmatch/logic/CElementDeleter.cpp +++ b/Client/mods/deathmatch/logic/CElementDeleter.cpp @@ -88,6 +88,7 @@ void CElementDeleter::DeleteRecursive(class CClientEntity* pElement) void CElementDeleter::DoDeleteAll() { + CPerformanceRecorder::Sample sample("CElementDeleter::DoDeleteAll"); // Make sure elements won't call us back and screw with our list (would crash) m_bAllowUnreference = false; diff --git a/Client/mods/deathmatch/logic/CMovingObjectsManager.cpp b/Client/mods/deathmatch/logic/CMovingObjectsManager.cpp index d64b45e4d17..2a230f5171c 100644 --- a/Client/mods/deathmatch/logic/CMovingObjectsManager.cpp +++ b/Client/mods/deathmatch/logic/CMovingObjectsManager.cpp @@ -14,6 +14,7 @@ void CMovingObjectsManager::DoPulse() { + CPerformanceRecorder::Sample sample("CMovingObjectsManager::DoPulse"); using Iterator = std::list::iterator; for (Iterator iter = m_List.begin(); iter != m_List.end(); /* manual increment */) diff --git a/Client/mods/deathmatch/logic/CPedSync.cpp b/Client/mods/deathmatch/logic/CPedSync.cpp index d11e8f526f0..41ab2cc2e46 100644 --- a/Client/mods/deathmatch/logic/CPedSync.cpp +++ b/Client/mods/deathmatch/logic/CPedSync.cpp @@ -55,6 +55,7 @@ bool CPedSync::ProcessPacket(unsigned char ucPacketID, NetBitStreamInterface& Bi void CPedSync::DoPulse() { + CPerformanceRecorder::Sample sample("CPedSync::DoPulse"); // Got any items? if (m_List.size() > 0) { diff --git a/Client/mods/deathmatch/logic/CUnoccupiedVehicleSync.cpp b/Client/mods/deathmatch/logic/CUnoccupiedVehicleSync.cpp index e341edcbed4..a96035be5e7 100644 --- a/Client/mods/deathmatch/logic/CUnoccupiedVehicleSync.cpp +++ b/Client/mods/deathmatch/logic/CUnoccupiedVehicleSync.cpp @@ -56,6 +56,7 @@ bool CUnoccupiedVehicleSync::ProcessPacket(unsigned char ucPacketID, NetBitStrea void CUnoccupiedVehicleSync::DoPulse() { + CPerformanceRecorder::Sample sample("CUnoccupiedVehicleSync::DoPulse"); // Check all our vehicles for damage UpdateDamageModels(); diff --git a/Client/mods/deathmatch/logic/lua/CLuaMain.cpp b/Client/mods/deathmatch/logic/lua/CLuaMain.cpp index 4f97dc44ba4..589d96c850c 100644 --- a/Client/mods/deathmatch/logic/lua/CLuaMain.cpp +++ b/Client/mods/deathmatch/logic/lua/CLuaMain.cpp @@ -508,6 +508,7 @@ const SString& CLuaMain::GetFunctionTag(int iLuaFunction) /////////////////////////////////////////////////////////////// int CLuaMain::PCall(lua_State* L, int nargs, int nresults, int errfunc) { + CPerformanceRecorder::Sample sample("CLuaMain::PCall"); TIMING_CHECKPOINT("+pcall"); g_pClientGame->ChangeFloatPrecision(true); g_pClientGame->GetScriptDebugging()->PushLuaMain(this); diff --git a/Client/mods/deathmatch/logic/lua/CLuaManager.cpp b/Client/mods/deathmatch/logic/lua/CLuaManager.cpp index 0f41e7396e7..2696eab49db 100644 --- a/Client/mods/deathmatch/logic/lua/CLuaManager.cpp +++ b/Client/mods/deathmatch/logic/lua/CLuaManager.cpp @@ -110,6 +110,8 @@ void CLuaManager::ProcessPendingDeleteList() void CLuaManager::DoPulse() { + CPerformanceRecorder::Sample sample("CLuaManager::DoPulse"); + sample.SetArg("Virtual machines count", m_virtualMachines.size()); list::iterator iter = m_virtualMachines.begin(); for (; iter != m_virtualMachines.end(); ++iter) { diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaElementDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaElementDefs.cpp index c3b7def7b66..fb064817b78 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaElementDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaElementDefs.cpp @@ -1711,6 +1711,7 @@ int CLuaElementDefs::SetElementID(lua_State* luaVM) int CLuaElementDefs::SetElementData(lua_State* luaVM) { + CPerformanceRecorder::FunctionSample sample("SetElementData"); // bool setElementData ( element theElement, string key, var value, [bool synchronize = true] ) CClientEntity* pEntity; SString strKey; @@ -1735,7 +1736,8 @@ int CLuaElementDefs::SetElementData(lua_State* luaVM) *SString("string length reduced to %d characters at argument 2", MAX_CUSTOMDATA_NAME_LENGTH))); strKey = strKey.Left(MAX_CUSTOMDATA_NAME_LENGTH); } - + sample.SetArg("Key", strKey); + sample.SetArg("Synchronized", bSynchronize); if (CStaticFunctionDefinitions::SetElementData(*pEntity, strKey, value, bSynchronize)) { lua_pushboolean(luaVM, true); diff --git a/Server/mods/deathmatch/logic/CGame.cpp b/Server/mods/deathmatch/logic/CGame.cpp index 75dc93d612d..3766a046933 100644 --- a/Server/mods/deathmatch/logic/CGame.cpp +++ b/Server/mods/deathmatch/logic/CGame.cpp @@ -420,10 +420,17 @@ void CGame::DoPulse() UNCLOCK1("HTTPDownloadManager"); } - CLOCK_CALL1(m_pPlayerManager->DoPulse();); + { + CPerformanceRecorder::Sample sample("CPlayerManager::DoPulse"); + CLOCK_CALL1(m_pPlayerManager->DoPulse();); + + } - // Pulse the net interface - CLOCK_CALL1(g_pNetServer->DoPulse();); + { + CPerformanceRecorder::Sample sample("CNetServerBuffer::DoPulse"); + // Pulse the net interface + CLOCK_CALL1(g_pNetServer->DoPulse();); + } if (m_pLanBroadcast) { diff --git a/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp b/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp index 0c15e23611c..4683fff0c74 100644 --- a/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp +++ b/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp @@ -878,13 +878,10 @@ bool CStaticFunctionDefinitions::SetElementData(CElement* pElement, const char* assert(pElement); assert(szName); assert(strlen(szName) <= MAX_CUSTOMDATA_NAME_LENGTH); - CPerformanceRecorder::FunctionSample sample("setElementData"); ESyncType lastSyncType = ESyncType::BROADCAST; CLuaArgument* pCurrentVariable = pElement->GetCustomData(szName, false, &lastSyncType); - sample.SetArg("Sync type", EnumToString(syncType)); - sample.SetArg("Key", szName); if (!pCurrentVariable || *pCurrentVariable != Variable || lastSyncType != syncType) { if (syncType != ESyncType::LOCAL) diff --git a/Server/mods/deathmatch/logic/luadefs/CLuaElementDefs.cpp b/Server/mods/deathmatch/logic/luadefs/CLuaElementDefs.cpp index cba5074706f..766f091f991 100644 --- a/Server/mods/deathmatch/logic/luadefs/CLuaElementDefs.cpp +++ b/Server/mods/deathmatch/logic/luadefs/CLuaElementDefs.cpp @@ -1546,6 +1546,7 @@ int CLuaElementDefs::setElementID(lua_State* luaVM) int CLuaElementDefs::setElementData(lua_State* luaVM) { + CPerformanceRecorder::FunctionSample sample("setElementData"); // bool setElementData ( element theElement, string key, var value, [var syncMode = true] ) CElement* pElement; SString strKey; @@ -1579,6 +1580,8 @@ int CLuaElementDefs::setElementData(lua_State* luaVM) strKey = strKey.Left(MAX_CUSTOMDATA_NAME_LENGTH); } + sample.SetArg("Sync type", EnumToString(syncType)); + sample.SetArg("Key", strKey); if (CStaticFunctionDefinitions::SetElementData(pElement, strKey, value, syncType)) { lua_pushboolean(luaVM, true); diff --git a/Shared/sdk/profiler/CPerformanceRecorder.cpp b/Shared/sdk/profiler/CPerformanceRecorder.cpp index d0936e20276..d0c7c047eb5 100644 --- a/Shared/sdk/profiler/CPerformanceRecorder.cpp +++ b/Shared/sdk/profiler/CPerformanceRecorder.cpp @@ -119,6 +119,26 @@ void CPerformanceRecorder::Sample::SetArg(const char* szKey, const char* value) json_object_object_add(args, szKey, json_object_new_string(value)); } +void CPerformanceRecorder::Sample::SetArg(const char* szKey, bool value) +{ + if (!m_enabled) + return; + +#ifdef MTA_CLIENT + json_object* object = g_pClientGame->GetPerformanceRecorder()->GetSampleObject(); +#else + json_object* object = g_pGame->GetPerformanceRecorder()->GetSampleObject(); +#endif + json_object* args = json_object_object_get(object, "args"); + if (!args) + { + args = json_object_new_object(); + json_object_object_add(object, "args", args); + } + + json_object_object_add(args, szKey, json_object_new_boolean(value)); +} + void CPerformanceRecorder::Sample::SetArg(const char* szKey, int value) { if (!m_enabled) @@ -139,7 +159,27 @@ void CPerformanceRecorder::Sample::SetArg(const char* szKey, int value) json_object_object_add(args, szKey, json_object_new_int(value)); } -CPerformanceRecorder::Sample::~Sample() +void CPerformanceRecorder::Sample::SetArg(const char* szKey, size_t value) +{ + if (!m_enabled) + return; + +#ifdef MTA_CLIENT + json_object* object = g_pClientGame->GetPerformanceRecorder()->GetSampleObject(); +#else + json_object* object = g_pGame->GetPerformanceRecorder()->GetSampleObject(); +#endif + json_object* args = json_object_object_get(object, "args"); + if (!args) + { + args = json_object_new_object(); + json_object_object_add(object, "args", args); + } + + json_object_object_add(args, szKey, json_object_new_int64(value)); +} + +void CPerformanceRecorder::Sample::Exit() { if (!m_enabled) return; @@ -156,7 +196,7 @@ CPerformanceRecorder::Sample::~Sample() json_object_object_add(object, "cat", json_object_new_string("default")); json_object_object_add(object, "ph", json_object_new_string("X")); - json_object_object_add(object, "ts", json_object_new_int64(m_startTime)); // int64 prevents int32 overflowing in this case. + json_object_object_add(object, "ts", json_object_new_int64(m_startTime)); // int64 prevents int32 overflowing in this case. json_object_object_add(object, "dur", json_object_new_int(GetTimeUs() - m_startTime)); json_object_object_add(object, "tid", json_object_new_int(getpid())); @@ -165,4 +205,10 @@ CPerformanceRecorder::Sample::~Sample() #else g_pGame->GetPerformanceRecorder()->ExitScope(); #endif + m_enabled = false; +} + +CPerformanceRecorder::Sample::~Sample() +{ + Exit(); } diff --git a/Shared/sdk/profiler/CPerformanceRecorder.h b/Shared/sdk/profiler/CPerformanceRecorder.h index f376bcd9cf6..07046f6702e 100644 --- a/Shared/sdk/profiler/CPerformanceRecorder.h +++ b/Shared/sdk/profiler/CPerformanceRecorder.h @@ -28,6 +28,10 @@ class CPerformanceRecorder void SetArg(const char* szKey, const char* value); void SetArg(const char* szKey, int value); + void SetArg(const char* szKey, size_t value); + void SetArg(const char* szKey, bool value); + + void Exit(); protected: std::string m_name; From eb950c474025fbc5855465a9936db78850147232 Mon Sep 17 00:00:00 2001 From: CrosRoad95 Date: Sun, 21 Mar 2021 09:15:18 +0100 Subject: [PATCH 10/10] fixes, fix crashes when client reconnect --- Client/mods/deathmatch/logic/CClientGame.cpp | 3 +- Client/mods/deathmatch/logic/CClientGame.h | 6 +-- .../logic/luadefs/CLuaElementDefs.cpp | 2 +- Shared/sdk/profiler/CPerformanceRecorder.cpp | 37 +++++++------------ Shared/sdk/profiler/CPerformanceRecorder.h | 7 ++-- 5 files changed, 22 insertions(+), 33 deletions(-) diff --git a/Client/mods/deathmatch/logic/CClientGame.cpp b/Client/mods/deathmatch/logic/CClientGame.cpp index 214606fd736..78e5ba771ad 100644 --- a/Client/mods/deathmatch/logic/CClientGame.cpp +++ b/Client/mods/deathmatch/logic/CClientGame.cpp @@ -184,7 +184,7 @@ CClientGame::CClientGame(bool bLocalPlay) : m_ServerInfo(new CServerInfo()) m_pScriptKeyBinds = new CScriptKeyBinds; m_pRemoteCalls = new CRemoteCalls(); m_pResourceFileDownloadManager = new CResourceFileDownloadManager(); - m_pPerformanceRecorder = new CPerformanceRecorder(); + m_pPerformanceRecorder = std::make_unique(); // Create our net API m_pNetAPI = new CNetAPI(m_pManager); @@ -480,7 +480,6 @@ CClientGame::~CClientGame() SAFE_DELETE(m_pLuaManager); SAFE_DELETE(m_pLatentTransferManager); SAFE_DELETE(m_pResourceFileDownloadManager); - SAFE_DELETE(m_pPerformanceRecorder); SAFE_DELETE(m_pRootEntity); diff --git a/Client/mods/deathmatch/logic/CClientGame.h b/Client/mods/deathmatch/logic/CClientGame.h index e9d44cc1ecd..4efaafacce5 100644 --- a/Client/mods/deathmatch/logic/CClientGame.h +++ b/Client/mods/deathmatch/logic/CClientGame.h @@ -299,7 +299,7 @@ class CClientGame CLatentTransferManager* GetLatentTransferManager() { return m_pLatentTransferManager; } CClientModelCacheManager* GetModelCacheManager() { return m_pModelCacheManager; } CDebugHookManager* GetDebugHookManager() { return m_pDebugHookManager; } - CPerformanceRecorder* GetPerformanceRecorder() const { return m_pPerformanceRecorder; } + CPerformanceRecorder* GetPerformanceRecorder() const { return m_pPerformanceRecorder.get(); } CElementDeleter* GetElementDeleter() { return &m_ElementDeleter; } CObjectRespawner* GetObjectRespawner() { return &m_ObjectRespawner; } @@ -689,7 +689,6 @@ class CClientGame CDebugHookManager* m_pDebugHookManager; CRemoteCalls* m_pRemoteCalls; CResourceFileDownloadManager* m_pResourceFileDownloadManager; - CPerformanceRecorder* m_pPerformanceRecorder; // Revised facilities CServer m_Server; @@ -705,7 +704,8 @@ class CClientGame CScriptDebugging* m_pScriptDebugging; CRegisteredCommands m_RegisteredCommands; - std::unique_ptr m_ServerInfo; + std::unique_ptr m_ServerInfo; + std::unique_ptr m_pPerformanceRecorder; // Map statuses SString m_strCurrentMapName; diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaElementDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaElementDefs.cpp index fb064817b78..b70908bcef5 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaElementDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaElementDefs.cpp @@ -1737,7 +1737,7 @@ int CLuaElementDefs::SetElementData(lua_State* luaVM) strKey = strKey.Left(MAX_CUSTOMDATA_NAME_LENGTH); } sample.SetArg("Key", strKey); - sample.SetArg("Synchronized", bSynchronize); + sample.SetBool("Synchronized", bSynchronize); if (CStaticFunctionDefinitions::SetElementData(*pEntity, strKey, value, bSynchronize)) { lua_pushboolean(luaVM, true); diff --git a/Shared/sdk/profiler/CPerformanceRecorder.cpp b/Shared/sdk/profiler/CPerformanceRecorder.cpp index d0c7c047eb5..2b6834ffefb 100644 --- a/Shared/sdk/profiler/CPerformanceRecorder.cpp +++ b/Shared/sdk/profiler/CPerformanceRecorder.cpp @@ -6,7 +6,11 @@ CPerformanceRecorder::CPerformanceRecorder() : m_start(GetTimeUs()), m_samples(j CPerformanceRecorder::~CPerformanceRecorder() { - json_object_put(m_samples); + if (m_samples) + { + json_object_put(m_samples); + m_samples = nullptr; + } } void CPerformanceRecorder::Start() @@ -88,11 +92,18 @@ CPerformanceRecorder::EventSample::~EventSample() CPerformanceRecorder::Sample::Sample(const char* name) : m_name(name), m_startTime(GetTimeUs()) { + #ifdef MTA_CLIENT + if (!g_pClientGame) + return; + m_enabled = g_pClientGame->GetPerformanceRecorder()->m_bRecordPerformance; if (m_enabled) g_pClientGame->GetPerformanceRecorder()->EnterScope(); #else + if (!g_pGame) + return; + m_enabled = g_pGame->GetPerformanceRecorder()->m_bRecordPerformance; if (m_enabled) g_pGame->GetPerformanceRecorder()->EnterScope(); @@ -119,7 +130,7 @@ void CPerformanceRecorder::Sample::SetArg(const char* szKey, const char* value) json_object_object_add(args, szKey, json_object_new_string(value)); } -void CPerformanceRecorder::Sample::SetArg(const char* szKey, bool value) +void CPerformanceRecorder::Sample::SetBool(const char* szKey, bool value) { if (!m_enabled) return; @@ -139,27 +150,7 @@ void CPerformanceRecorder::Sample::SetArg(const char* szKey, bool value) json_object_object_add(args, szKey, json_object_new_boolean(value)); } -void CPerformanceRecorder::Sample::SetArg(const char* szKey, int value) -{ - if (!m_enabled) - return; - -#ifdef MTA_CLIENT - json_object* object = g_pClientGame->GetPerformanceRecorder()->GetSampleObject(); -#else - json_object* object = g_pGame->GetPerformanceRecorder()->GetSampleObject(); -#endif - json_object* args = json_object_object_get(object, "args"); - if (!args) - { - args = json_object_new_object(); - json_object_object_add(object, "args", args); - } - - json_object_object_add(args, szKey, json_object_new_int(value)); -} - -void CPerformanceRecorder::Sample::SetArg(const char* szKey, size_t value) +void CPerformanceRecorder::Sample::SetArg(const char* szKey, int64_t value) { if (!m_enabled) return; diff --git a/Shared/sdk/profiler/CPerformanceRecorder.h b/Shared/sdk/profiler/CPerformanceRecorder.h index 07046f6702e..aeb193c05cb 100644 --- a/Shared/sdk/profiler/CPerformanceRecorder.h +++ b/Shared/sdk/profiler/CPerformanceRecorder.h @@ -27,15 +27,14 @@ class CPerformanceRecorder virtual ~Sample(); void SetArg(const char* szKey, const char* value); - void SetArg(const char* szKey, int value); - void SetArg(const char* szKey, size_t value); - void SetArg(const char* szKey, bool value); + void SetArg(const char* szKey, int64_t value); + void SetBool(const char* szKey, bool value); void Exit(); protected: std::string m_name; - bool m_enabled; + bool m_enabled = false; private: TIMEUS m_startTime = 0;