From f3372bf11d341032723dc6c5d14e2c4c42120e90 Mon Sep 17 00:00:00 2001 From: Ykkrosh Date: Sat, 19 Feb 2011 03:14:37 +0000 Subject: [PATCH] Add some rough performance reporting. Make the profiler converge a bit faster. This was SVN commit r8939. --- .../data/mods/public/gui/session/session.js | 17 ++++++ source/graphics/MapWriter.cpp | 2 +- source/gui/scripting/ScriptFunctions.cpp | 21 +++++++ source/ps/Profile.h | 2 +- source/ps/ProfileViewer.cpp | 56 ++++++++++++++++++- source/ps/ProfileViewer.h | 8 +++ source/simulation2/Simulation2.cpp | 7 ++- source/simulation2/Simulation2.h | 7 ++- 8 files changed, 115 insertions(+), 5 deletions(-) diff --git a/binaries/data/mods/public/gui/session/session.js b/binaries/data/mods/public/gui/session/session.js index 877383d70e..6b40b75370 100644 --- a/binaries/data/mods/public/gui/session/session.js +++ b/binaries/data/mods/public/gui/session/session.js @@ -83,6 +83,23 @@ function init(initData, hotloadData) getGUIObjectByName("civIcon").sprite = "stretched:"+g_CivData[g_Players[Engine.GetPlayerID()].civ].Emblem; onSimulationUpdate(); + + // Report the performance after 5 seconds (when we're still near + // the initial camera view) and a minute (when the profiler will + // have settled down if framerates as very low), to give some + // extremely rough indications of performance + setTimeout(function() { reportPerformance(5); }, 5000); + setTimeout(function() { reportPerformance(60); }, 60000); +} + +function reportPerformance(time) +{ + var data = { + time: time, + map: Engine.GetMapSettings().Name, + profiler: Engine.GetProfilerState() + }; + Engine.SubmitUserReport("profile", 1, JSON.stringify(data)); } function leaveGame() diff --git a/source/graphics/MapWriter.cpp b/source/graphics/MapWriter.cpp index bc281976c5..36363f885a 100644 --- a/source/graphics/MapWriter.cpp +++ b/source/graphics/MapWriter.cpp @@ -279,7 +279,7 @@ void CMapWriter::WriteXML(const VfsPath& filename, if (pSimulation2) { - std::string settings = pSimulation2->GetMapSettings(); + std::string settings = pSimulation2->GetMapSettingsString(); if (!settings.empty()) { XML_Element("ScriptSettings"); diff --git a/source/gui/scripting/ScriptFunctions.cpp b/source/gui/scripting/ScriptFunctions.cpp index ec015210d3..cd9081f03c 100644 --- a/source/gui/scripting/ScriptFunctions.cpp +++ b/source/gui/scripting/ScriptFunctions.cpp @@ -36,6 +36,7 @@ #include "ps/Game.h" #include "ps/Hotkey.h" #include "ps/Overlay.h" +#include "ps/ProfileViewer.h" #include "ps/Pyrogenesis.h" #include "ps/UserReport.h" #include "ps/GameSetup/Atlas.h" @@ -317,6 +318,18 @@ CScriptVal LoadMapSettings(void* cbdata, std::wstring pathname) return reader.GetMapSettings(guiManager->GetScriptInterface()).get(); } +CScriptVal GetMapSettings(void* cbdata) +{ + CGUIManager* guiManager = static_cast (cbdata); + + if (!g_Game) + return CScriptVal(); + + return guiManager->GetScriptInterface().CloneValueFromOtherContext( + g_Game->GetSimulation2()->GetScriptInterface(), + g_Game->GetSimulation2()->GetMapSettings().get()); +} + /** * Start / stop camera following mode * @param entityid unit id to follow. If zero, stop following mode @@ -343,6 +356,12 @@ void DisplayErrorDialog(void* UNUSED(cbdata), std::wstring msg) debug_DisplayError(msg.c_str(), DE_NO_DEBUG_INFO, NULL, NULL, NULL, 0, NULL, NULL); } +CScriptVal GetProfilerState(void* cbdata) +{ + CGUIManager* guiManager = static_cast (cbdata); + + return g_ProfileViewer.SaveToJS(guiManager->GetScriptInterface()); +} bool IsUserReportEnabled(void* UNUSED(cbdata)) @@ -469,10 +488,12 @@ void GuiScriptingInit(ScriptInterface& scriptInterface) scriptInterface.RegisterFunction("RestartInAtlas"); scriptInterface.RegisterFunction("AtlasIsAvailable"); scriptInterface.RegisterFunction("LoadMapSettings"); + scriptInterface.RegisterFunction("GetMapSettings"); scriptInterface.RegisterFunction("CameraFollow"); scriptInterface.RegisterFunction("CameraFollowFPS"); scriptInterface.RegisterFunction("HotkeyIsPressed"); scriptInterface.RegisterFunction("DisplayErrorDialog"); + scriptInterface.RegisterFunction("GetProfilerState"); // User report functions scriptInterface.RegisterFunction("IsUserReportEnabled"); diff --git a/source/ps/Profile.h b/source/ps/Profile.h index 06a65a745a..b6675a7e34 100644 --- a/source/ps/Profile.h +++ b/source/ps/Profile.h @@ -28,7 +28,7 @@ #include "ps/ThreadUtil.h" #define PROFILE_AMORTIZE -#define PROFILE_AMORTIZE_FRAMES 50 +#define PROFILE_AMORTIZE_FRAMES 30 class CProfileManager; class CProfileNodeTable; diff --git a/source/ps/ProfileViewer.cpp b/source/ps/ProfileViewer.cpp index fc19655db0..62e27136df 100644 --- a/source/ps/ProfileViewer.cpp +++ b/source/ps/ProfileViewer.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2009 Wildfire Games. +/* Copyright (C) 2011 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -36,6 +36,7 @@ #include "lib/external_libraries/sdl.h" #include "lib/res/graphics/unifont.h" #include "renderer/Renderer.h" +#include "scriptinterface/ScriptInterface.h" extern int g_xres, g_yres; @@ -429,6 +430,47 @@ namespace const WriteTable& operator=(const WriteTable&); }; + struct DumpTable + { + ScriptInterface& scriptInterface; + CScriptVal root; + DumpTable(ScriptInterface& scriptInterface, CScriptVal root) : + scriptInterface(scriptInterface), root(root) + { + } + + void operator() (AbstractProfileTable* table) + { + scriptInterface.SetProperty(root.get(), table->GetTitle().c_str(), DumpRows(table)); + } + + CScriptVal DumpRows(AbstractProfileTable* table) + { + CScriptVal data; + scriptInterface.Eval("({})", data); + + const std::vector& columns = table->GetColumns(); + + for (size_t r = 0; r < table->GetNumberRows(); ++r) + { + CScriptVal row; + scriptInterface.Eval("({})", row); + scriptInterface.SetProperty(data.get(), table->GetCellText(r, 0).c_str(), row); + + for (size_t c = 1; c < columns.size(); ++c) + scriptInterface.SetProperty(row.get(), columns[c].title.c_str(), table->GetCellText(r, c)); + + if (table->GetChild(r)) + scriptInterface.SetProperty(row.get(), "children", DumpRows(table->GetChild(r))); + } + + return data; + } + + private: + const DumpTable& operator=(const DumpTable&); + }; + bool SortByName(AbstractProfileTable* a, AbstractProfileTable* b) { return (a->GetName() < b->GetName()); @@ -467,6 +509,18 @@ void CProfileViewer::SaveToFile() m->outputStream.flush(); } +CScriptVal CProfileViewer::SaveToJS(ScriptInterface& scriptInterface) +{ + CScriptVal root; + scriptInterface.Eval("({})", root); + + std::vector tables = m->rootTables; + sort(tables.begin(), tables.end(), SortByName); + for_each(tables.begin(), tables.end(), DumpTable(scriptInterface, root)); + + return root; +} + void CProfileViewer::ShowTable(const CStr& table) { m->path.clear(); diff --git a/source/ps/ProfileViewer.h b/source/ps/ProfileViewer.h index ce3144dfef..d452b0d55b 100644 --- a/source/ps/ProfileViewer.h +++ b/source/ps/ProfileViewer.h @@ -26,6 +26,8 @@ #include "ps/CStr.h" #include "ps/Singleton.h" +class ScriptInterface; +class CScriptVal; /** * Struct ProfileColumn: Describes one column of an AbstractProfileTable. @@ -181,6 +183,12 @@ public: */ void SaveToFile(); + /** + * SaveToJS: Return a script value containing the current profiler data + * (for all profile tables). + */ + CScriptVal SaveToJS(ScriptInterface& scriptInterface); + /** * ShowTable: Set the named profile table to be the displayed one. If it * is not found, no profile is displayed. diff --git a/source/simulation2/Simulation2.cpp b/source/simulation2/Simulation2.cpp index 60902ecb7c..4b764183c0 100644 --- a/source/simulation2/Simulation2.cpp +++ b/source/simulation2/Simulation2.cpp @@ -419,11 +419,16 @@ void CSimulation2::SetMapSettings(const CScriptValRooted& settings) m->m_MapSettings = settings; } -std::string CSimulation2::GetMapSettings() +std::string CSimulation2::GetMapSettingsString() { return m->m_ComponentManager.GetScriptInterface().StringifyJSON(m->m_MapSettings.get()); } +CScriptVal CSimulation2::GetMapSettings() +{ + return m->m_MapSettings.get(); +} + void CSimulation2::LoadPlayerSettings() { GetScriptInterface().CallFunctionVoid(GetScriptInterface().GetGlobalObject(), "LoadPlayerSettings", m->m_MapSettings); diff --git a/source/simulation2/Simulation2.h b/source/simulation2/Simulation2.h index 6d94c4f4c0..59c2aa5156 100644 --- a/source/simulation2/Simulation2.h +++ b/source/simulation2/Simulation2.h @@ -100,7 +100,12 @@ public: /** * Get the current map settings as a UTF-8 JSON string. */ - std::string GetMapSettings(); + std::string GetMapSettingsString(); + + /** + * Get the current map settings. + */ + CScriptVal GetMapSettings(); /** * Reload any scripts that were loaded from the given filename.