summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrei Karas <akaras@inbox.ru>2018-09-07 20:58:59 +0300
committerAndrei Karas <akaras@inbox.ru>2018-09-07 20:58:59 +0300
commit32b9e2070b3cf44b6b38ab0c0383b85e87852d50 (patch)
tree352d7a4c3dcb8fbffadeb127cee0090aa98d073a
parentabfc18794cbd9119c110f32e39ea48a00e5b9214 (diff)
downloadmv-32b9e2070b3cf44b6b38ab0c0383b85e87852d50.tar.gz
mv-32b9e2070b3cf44b6b38ab0c0383b85e87852d50.tar.bz2
mv-32b9e2070b3cf44b6b38ab0c0383b85e87852d50.tar.xz
mv-32b9e2070b3cf44b6b38ab0c0383b85e87852d50.zip
Add basic performance counters.
Add in debug window new tab with this counters.
-rw-r--r--src/CMakeLists.txt3
-rw-r--r--src/Makefile.am3
-rw-r--r--src/const/utils/perfstat.h29
-rw-r--r--src/game.cpp3
-rw-r--r--src/gui/widgets/tabs/statdebugtab.cpp60
-rw-r--r--src/gui/widgets/tabs/statdebugtab.h14
-rw-r--r--src/progs/manaplus/client.cpp34
-rw-r--r--src/utils/perfstat.cpp127
-rw-r--r--src/utils/perfstat.h62
9 files changed, 333 insertions, 2 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 6bd5cb8a8..b4433b8cc 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -940,6 +940,8 @@ SET(SRCS
fs/paths.h
utils/perfomance.cpp
utils/perfomance.h
+ utils/perfstat.cpp
+ utils/perfstat.h
utils/pnglib.cpp
utils/pnglib.h
fs/virtfs/fsfuncs.h
@@ -1128,6 +1130,7 @@ SET(SRCS
const/equipment.h
const/itemshortcut.h
const/spells.h
+ const/utils/perfstat.h
const/utils/timer.h
const/utils/utf8.h
const/gui/chat.h
diff --git a/src/Makefile.am b/src/Makefile.am
index b55b7a237..ef905997e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -641,6 +641,8 @@ BASE_SRC += client.h \
fs/paths.h \
utils/perfomance.cpp \
utils/perfomance.h \
+ utils/perfstat.cpp \
+ utils/perfstat.h \
utils/pnglib.cpp \
utils/pnglib.h \
fs/virtfs/fsfuncs.h \
@@ -719,6 +721,7 @@ BASE_SRC += client.h \
const/equipment.h \
const/itemshortcut.h \
const/spells.h \
+ const/utils/perfstat.h \
const/utils/timer.h \
const/utils/utf8.h \
const/gui/chat.h \
diff --git a/src/const/utils/perfstat.h b/src/const/utils/perfstat.h
new file mode 100644
index 000000000..9f7430516
--- /dev/null
+++ b/src/const/utils/perfstat.h
@@ -0,0 +1,29 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2018 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef CONST_UTILS_PERFSTAT_H
+#define CONST_UTILS_PERFSTAT_H
+
+#include "localconsts.h"
+
+static const int PERFSTAT_MAX = 120;
+static const int PERFSTAT_LAST_STAT = 13;
+
+#endif // CONST_UTILS_PERFSTAT_H
diff --git a/src/game.cpp b/src/game.cpp
index bfbaba353..eadfda7f6 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -125,6 +125,7 @@
#include "utils/delete2.h"
#include "utils/foreach.h"
#include "utils/gettext.h"
+#include "utils/perfstat.h"
#include "utils/pnglib.h"
#include "utils/sdlcheckutils.h"
#include "utils/timer.h"
@@ -1092,6 +1093,7 @@ void Game::changeMap(const std::string &mapPath)
{
BLOCK_START("Game::changeMap")
+ skipPerfFrames = 3;
resetAdjustLevel();
ResourceManager::cleanProtected();
@@ -1182,6 +1184,7 @@ void Game::changeMap(const std::string &mapPath)
localPlayer->recreateItemParticles();
gameHandler->mapLoadedEvent();
+ Perf::init();
BLOCK_END("Game::changeMap")
}
diff --git a/src/gui/widgets/tabs/statdebugtab.cpp b/src/gui/widgets/tabs/statdebugtab.cpp
index 29fca62de..6d4f8afa4 100644
--- a/src/gui/widgets/tabs/statdebugtab.cpp
+++ b/src/gui/widgets/tabs/statdebugtab.cpp
@@ -20,11 +20,17 @@
#include "gui/widgets/tabs/statdebugtab.h"
+#include "const/utils/timer.h"
+
+#include "gui/widgets/button.h"
#include "gui/widgets/containerplacer.h"
#include "gui/widgets/label.h"
#include "gui/widgets/layouthelper.h"
+#include "gui/windows/chatwindow.h"
+
#include "utils/gettext.h"
+#include "utils/perfstat.h"
#include "utils/stringutils.h"
#include "utils/timer.h"
@@ -33,12 +39,27 @@
StatDebugTab::StatDebugTab(const Widget2 *const widget) :
DebugTab(widget),
// TRANSLATORS: debug window label, logic per second
- mLPSLabel(new Label(this, strprintf(_("LPS: %d"), 0)))
+ mLPSLabel(new Label(this, strprintf(_("LPS: %d"), 0))),
+ // TRANSLATORS: debug window stats reset button
+ mResetButton(new Button(this, _("Reset"), "reset", BUTTON_SKIN, this)),
+ // TRANSLATORS: debug window stats copy button
+ mCopyButton(new Button(this, _("Copy"), "copy", BUTTON_SKIN, this)),
+ mStatLabels(),
+ mDrawIndex(0)
{
LayoutHelper h(this);
ContainerPlacer place = h.getPlacer(0, 0);
place(0, 0, mLPSLabel, 2, 1);
+ place(0, 1, mResetButton, 1, 1);
+ place(1, 1, mCopyButton, 1, 1);
+ for (int f = 1; f < PERFSTAT_LAST_STAT; f ++)
+ {
+ mStatLabels[f - 1] = new Label(this,
+ // TRANSLATORS: debug window stat label
+ strprintf(_("stat%d: %d (%d) ms"), f, 0, 0));
+ place(0, f + 1, mStatLabels[f - 1], 2, 1);
+ }
place.getCell().matchColWidth(0, 0);
place = h.getPlacer(0, 1);
@@ -50,5 +71,42 @@ void StatDebugTab::logic()
BLOCK_START("StatDebugTab::logic")
// TRANSLATORS: debug window label, logic per second
mLPSLabel->setCaption(strprintf(_("LPS: %d"), lps));
+
+ for (int f = 1; f < PERFSTAT_LAST_STAT; f ++)
+ {
+ mStatLabels[f - 1]->setCaption(
+ // TRANSLATORS: debug window stat label
+ strprintf(_("stat%d: %d (%d) ms"),
+ f,
+ Perf::getTime(prevPerfFrameId, f) * MILLISECONDS_IN_A_TICK,
+ Perf::getWorstTime(f) * MILLISECONDS_IN_A_TICK));
+ }
+ mDrawIndex = prevPerfFrameId;
BLOCK_END("StatDebugTab::logic")
}
+
+void StatDebugTab::action(const ActionEvent &event)
+{
+ const std::string &eventId = event.getId();
+ if (eventId == "reset")
+ {
+ Perf::init();
+ }
+ else if (eventId == "copy")
+ {
+ std::string data("perf:");
+ for (int f = 1; f < PERFSTAT_LAST_STAT; f ++)
+ {
+ data.append(strprintf(" %d",
+ Perf::getTime(mDrawIndex, f) * MILLISECONDS_IN_A_TICK));
+ }
+ data.append(",");
+ for (int f = 1; f < PERFSTAT_LAST_STAT; f ++)
+ {
+ data.append(strprintf(" %d",
+ Perf::getWorstTime(f) * MILLISECONDS_IN_A_TICK));
+ }
+ chatWindow->addInputText(data,
+ true);
+ }
+}
diff --git a/src/gui/widgets/tabs/statdebugtab.h b/src/gui/widgets/tabs/statdebugtab.h
index d52ff63af..57b2e9f4a 100644
--- a/src/gui/widgets/tabs/statdebugtab.h
+++ b/src/gui/widgets/tabs/statdebugtab.h
@@ -23,9 +23,15 @@
#include "gui/widgets/tabs/debugtab.h"
+#include "const/utils/perfstat.h"
+
+#include "listeners/actionlistener.h"
+
+class Button;
class Label;
-class StatDebugTab final : public DebugTab
+class StatDebugTab final : public DebugTab,
+ public ActionListener
{
friend class DebugWindow;
@@ -36,8 +42,14 @@ class StatDebugTab final : public DebugTab
void logic() override final;
+ void action(const ActionEvent &event) override;
+
private:
Label *mLPSLabel A_NONNULLPOINTER;
+ Button *mResetButton A_NONNULLPOINTER;
+ Button *mCopyButton A_NONNULLPOINTER;
+ Label *mStatLabels[PERFSTAT_LAST_STAT - 1] A_NONNULLPOINTER;
+ size_t mDrawIndex;
};
#endif // GUI_WIDGETS_TABS_STATDEBUGTAB_H
diff --git a/src/progs/manaplus/client.cpp b/src/progs/manaplus/client.cpp
index 880f05a0b..01348db2d 100644
--- a/src/progs/manaplus/client.cpp
+++ b/src/progs/manaplus/client.cpp
@@ -127,6 +127,7 @@
#ifdef ANDROID
#include "fs/paths.h"
#endif // ANDROID
+#include "utils/perfstat.h"
#include "utils/sdlcheckutils.h"
#include "utils/sdlhelper.h"
#include "utils/timer.h"
@@ -952,20 +953,30 @@ int Client::gameExec()
{
int lastTickTime = tick_time;
+ Perf::init();
+
while (mState != State::EXIT)
{
PROFILER_START();
+ PERF_STAT(0);
if (eventsManager.handleEvents())
continue;
+ PERF_STAT(1);
+
BLOCK_START("Client::gameExec 3")
if (generalHandler != nullptr)
generalHandler->flushNetwork();
BLOCK_END("Client::gameExec 3")
+ PERF_STAT(2);
+
BLOCK_START("Client::gameExec 4")
if (gui != nullptr)
gui->logic();
+
+ PERF_STAT(3);
+
cur_time = time(nullptr);
int k = 0;
while (lastTickTime != tick_time &&
@@ -979,14 +990,28 @@ int Client::gameExec()
++lastTickTime;
k ++;
}
+
+ PERF_STAT(4);
+
soundManager.logic();
+ PERF_STAT(5);
+
logic_count += k;
if (gui != nullptr)
gui->slowLogic();
+
+ PERF_STAT(6);
+
if (mGame != nullptr)
mGame->slowLogic();
+
+ PERF_STAT(7);
+
slowLogic();
+
+ PERF_STAT(8);
+
BLOCK_END("Client::gameExec 4")
// This is done because at some point tick_time will wrap.
@@ -1005,11 +1030,15 @@ int Client::gameExec()
SDL_Delay(100);
}
+ PERF_STAT(9);
+
BLOCK_START("~Client::SDL_framerateDelay")
if (settings.limitFps)
SDL_framerateDelay(&fpsManager);
BLOCK_END("~Client::SDL_framerateDelay")
+ PERF_STAT(10);
+
BLOCK_START("Client::gameExec 6")
if (mState == State::CONNECT_GAME)
{
@@ -1034,6 +1063,8 @@ int Client::gameExec()
}
BLOCK_END("Client::gameExec 6")
+ PERF_STAT(11);
+
if (mState != mOldState)
{
BLOCK_START("Client::gameExec 7")
@@ -1373,6 +1404,7 @@ int Client::gameExec()
if (mumbleManager)
mumbleManager->setPlayer(localPlayer->getName());
#endif // USE_MUMBLE
+ Perf::init();
}
// Fade out logon-music here too to give the desired effect
@@ -1656,6 +1688,8 @@ int Client::gameExec()
}
BLOCK_END("Client::gameExec 8")
}
+ PERF_STAT(12);
+ PERF_NEXTFRAME();
PROFILER_END();
}
diff --git a/src/utils/perfstat.cpp b/src/utils/perfstat.cpp
new file mode 100644
index 000000000..839fc7291
--- /dev/null
+++ b/src/utils/perfstat.cpp
@@ -0,0 +1,127 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2018 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "utils/perfstat.h"
+
+#include "logger.h"
+
+#include "utils/timer.h"
+
+#include "debug.h"
+
+PerfStats perfStats[PERFSTAT_MAX];
+
+size_t perfFrameId = 0;
+size_t prevPerfFrameId = PERFSTAT_MAX;
+int *perfFrame = &perfStats[perfFrameId].ticks[0];
+PerfStats worstFrameStats;
+int worstTime = -1;
+int skipPerfFrames = -1;
+
+namespace Perf
+{
+ void init()
+ {
+ logger->log("perf stats init");
+ worstTime = -1;
+ perfFrameId = 0;
+ prevPerfFrameId = 0;
+ for (size_t f = 0; f < PERFSTAT_LAST_STAT; f ++)
+ {
+ worstFrameStats.ticks[f] = 0;
+ }
+ for (size_t f = 0; f < PERFSTAT_MAX; f ++)
+ {
+ PerfStats &perf = perfStats[f];
+ for (size_t d = 0; d < PERFSTAT_LAST_STAT; d ++)
+ {
+ perf.ticks[d] = 0;
+ }
+ }
+ skipPerfFrames = 0;
+ }
+
+ void nextFrame()
+ {
+ if (skipPerfFrames > 0)
+ {
+ skipPerfFrames --;
+// logger->log("skip frames: %d", skipPerfFrames);
+ return;
+ }
+ else if (skipPerfFrames < 0)
+ {
+ return;
+ }
+ prevPerfFrameId = perfFrameId;
+ perfFrameId ++;
+ if (perfFrameId >= PERFSTAT_MAX)
+ {
+ perfFrameId = 0;
+ selectWorstFrame();
+ }
+ perfFrame = &perfStats[perfFrameId].ticks[0];
+ }
+
+ void selectWorstFrame()
+ {
+ int time = worstTime;
+ int index = -1;
+ for (size_t f = 0; f < PERFSTAT_MAX; f ++)
+ {
+ if (f == perfFrameId)
+ continue;
+ const int time1 = Perf::getTime(f, PERFSTAT_LAST_STAT - 1);
+ if (time1 > time)
+ {
+ time = time1;
+ index = f;
+ }
+ }
+ if (index >= 0)
+ {
+ worstFrameStats = perfStats[index];
+ logger->log("worst frame: %d, %d",
+ perfStats[index].ticks[PERFSTAT_LAST_STAT - 1],
+ worstFrameStats.ticks[PERFSTAT_LAST_STAT - 1]);
+ worstTime = time;
+ }
+ }
+
+ int getTime(const size_t frameId,
+ const size_t counterId)
+ {
+ const PerfStats &perf = perfStats[frameId];
+ const int val1 = perf.ticks[0];
+ const int val2 = perf.ticks[counterId];
+ if (val2 >= val1)
+ return val2 - val1;
+ return val1 - val1;
+ }
+
+ int getWorstTime(const size_t counterId)
+ {
+ const int val1 = worstFrameStats.ticks[0];
+ const int val2 = worstFrameStats.ticks[counterId];
+ if (val2 >= val1)
+ return val2 - val1;
+ return val1 - val1;
+ }
+}
diff --git a/src/utils/perfstat.h b/src/utils/perfstat.h
new file mode 100644
index 000000000..97e5e1a07
--- /dev/null
+++ b/src/utils/perfstat.h
@@ -0,0 +1,62 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2018 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef UTILS_PERFSTAT_H
+#define UTILS_PERFSTAT_H
+
+#include "const/utils/perfstat.h"
+
+#include "localconsts.h"
+
+struct PerfStats
+{
+ PerfStats()
+ {
+ for (int f = 0; f < 16; f ++)
+ ticks[f] = -1;
+ }
+
+ int ticks[16];
+};
+
+namespace Perf
+{
+ void init();
+ void nextFrame();
+ void selectWorstFrame();
+ int getTime(const size_t frameId,
+ const size_t counterId);
+ int getWorstTime(const size_t counterId);
+}
+
+extern PerfStats perfStats[PERFSTAT_MAX];
+extern size_t perfFrameId;
+extern size_t prevPerfFrameId;
+extern int *perfFrame;
+extern PerfStats worstFrameStats;
+extern int skipPerfFrames;
+
+#define PERF_STAT(n) \
+ perfFrame[n] = tick_time
+
+#define PERF_NEXTFRAME() \
+ Perf::nextFrame()
+
+#endif // UTILS_PERFSTAT_H