mirror of
https://github.com/minetest/minetest.git
synced 2024-07-04 15:05:27 +02:00
Compare commits
6 Commits
b7f559698c
...
91d984f299
Author | SHA1 | Date | |
---|---|---|---|
|
91d984f299 | ||
|
be6c00d1b4 | ||
|
31337a0486 | ||
|
4dc3fd2fcc | ||
|
e41e2c43e8 | ||
|
7be7d15a02 |
@ -26,15 +26,28 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include <IVideoDriver.h>
|
#include <IVideoDriver.h>
|
||||||
#include "profiler.h"
|
#include "profiler.h"
|
||||||
|
|
||||||
/* Profiler display */
|
|
||||||
|
/** \brief Draws graph every frame using data given by Profiler.
|
||||||
|
|
||||||
|
It displays only entries that are recorded for profiler graph (via Profiler::graphAdd,
|
||||||
|
ScopeProfilerType::SPT_GRAPH_ADD and other) and Profiler itself doesn't show them.
|
||||||
|
|
||||||
|
Each profiling entry described with upper bound value, entry name and lower bound
|
||||||
|
value on its right. Graph is displayed as \e line if it is relative (lower value
|
||||||
|
is not 0) and \e filled if it is absolute.
|
||||||
|
|
||||||
|
\ingroup Profiling
|
||||||
|
*/
|
||||||
class ProfilerGraph
|
class ProfilerGraph
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
/// One-frame slice of graph values.
|
||||||
struct Piece
|
struct Piece
|
||||||
{
|
{
|
||||||
Piece(Profiler::GraphValues v) : values(std::move(v)) {}
|
Piece(Profiler::GraphValues v) : values(std::move(v)) {}
|
||||||
Profiler::GraphValues values;
|
Profiler::GraphValues values;
|
||||||
};
|
};
|
||||||
|
/// Data for drawing one graph. Updates every frame.
|
||||||
struct Meta
|
struct Meta
|
||||||
{
|
{
|
||||||
float min;
|
float min;
|
||||||
@ -54,6 +67,8 @@ class ProfilerGraph
|
|||||||
|
|
||||||
ProfilerGraph() = default;
|
ProfilerGraph() = default;
|
||||||
|
|
||||||
|
/// Adds graph values to the end of graph (rendered at right side) and
|
||||||
|
/// removes the oldest ones (beyond the `m_log_max_size`).
|
||||||
void put(const Profiler::GraphValues &values);
|
void put(const Profiler::GraphValues &values);
|
||||||
|
|
||||||
void draw(s32 x_left, s32 y_bottom, video::IVideoDriver *driver,
|
void draw(s32 x_left, s32 y_bottom, video::IVideoDriver *driver,
|
||||||
|
137
src/profiler.h
137
src/profiler.h
@ -29,22 +29,63 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "util/timetaker.h"
|
#include "util/timetaker.h"
|
||||||
#include "util/numeric.h" // paging()
|
#include "util/numeric.h" // paging()
|
||||||
|
|
||||||
// Global profiler
|
|
||||||
class Profiler;
|
|
||||||
extern Profiler *g_profiler;
|
|
||||||
|
|
||||||
/*
|
/** \defgroup Profiling Profiling tools
|
||||||
Time profiler
|
\brief Embedded tools to profile CPU time or anything else that is recorded
|
||||||
|
by certain functions.
|
||||||
|
|
||||||
|
An example with global profiler (#g_profiler), that is available in any file
|
||||||
|
with profiler.h included:
|
||||||
|
\code{.c++}
|
||||||
|
void functionToProfie(int count) {
|
||||||
|
// Record (add) time till function (scope) end
|
||||||
|
ScopeProfiler scope_profiler(g_profiler, "functionToProfie()"); // SPT_ADD by default
|
||||||
|
// Record (add) `count`
|
||||||
|
g_profiler->add("functionToProfie() count", count)
|
||||||
|
}
|
||||||
|
\endcode
|
||||||
|
In this example "add" method is used, so if function is called several times during
|
||||||
|
g_profiler cycle, sum of all recorded values will be shown at cycle end. See
|
||||||
|
#g_profiler for details about cycle and info showing.
|
||||||
|
|
||||||
|
TimeTaker can be used instead of ScopeProfiler.
|
||||||
|
\{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/** \brief Collects values (time intervals, counts and other) in named entries.
|
||||||
|
|
||||||
|
Can be used to get sum, average or maximum of recorded values for each entry. Gives
|
||||||
|
result in text form via print().
|
||||||
|
|
||||||
|
Can collect values for #ProfilerGraph and give them via graphPop().
|
||||||
|
|
||||||
|
For usage, see \ref Profiling.
|
||||||
|
*/
|
||||||
class Profiler
|
class Profiler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Profiler();
|
Profiler();
|
||||||
|
|
||||||
|
/** \brief Records the \p value in entry with given \p name to get sum of recorded values.
|
||||||
|
\param[in] name: entry name; can be same for several function calls
|
||||||
|
\param[in] value: value to record
|
||||||
|
*/
|
||||||
void add(const std::string &name, float value);
|
void add(const std::string &name, float value);
|
||||||
|
|
||||||
|
/** \brief Records the \p value in entry with given \p name to get average of recorded values.
|
||||||
|
\param[in] name: entry name; can be same for several function calls
|
||||||
|
\param[in] value: value to record
|
||||||
|
*/
|
||||||
void avg(const std::string &name, float value);
|
void avg(const std::string &name, float value);
|
||||||
|
|
||||||
|
/** \brief Records the \p value in entry with given \p name to get maximum of recorded values.
|
||||||
|
\param[in] name: entry name; can be same for several function calls
|
||||||
|
\param[in] value: value to record
|
||||||
|
*/
|
||||||
void max(const std::string &name, float value);
|
void max(const std::string &name, float value);
|
||||||
|
|
||||||
|
/// Clears all profiling entries (#m_data). Does not affect #m_graphvalues.
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
float getValue(const std::string &name) const;
|
float getValue(const std::string &name) const;
|
||||||
@ -53,16 +94,46 @@ class Profiler
|
|||||||
|
|
||||||
typedef std::map<std::string, float> GraphValues;
|
typedef std::map<std::string, float> GraphValues;
|
||||||
|
|
||||||
// Returns the line count
|
/** \brief Prints collected data formatted as table.
|
||||||
|
|
||||||
|
Prints each entry as one line which contains name, avgCount and value.
|
||||||
|
Meaning of printed numbers depends on used recording method (add/avg/max).
|
||||||
|
avgCount makes sense only for "avg" method and shows number of records;
|
||||||
|
always shows 1 for other methods.
|
||||||
|
|
||||||
|
Breaks all entries into \p pagecount pages and print only given \p page.
|
||||||
|
|
||||||
|
\param[out] o: stream to print into
|
||||||
|
\param[in] page: number of page to print
|
||||||
|
\param[in] pagecount: count of pages to break data into
|
||||||
|
\returns printed line count
|
||||||
|
*/
|
||||||
int print(std::ostream &o, u32 page = 1, u32 pagecount = 1);
|
int print(std::ostream &o, u32 page = 1, u32 pagecount = 1);
|
||||||
|
|
||||||
|
/** \brief Breaks #m_data (entries) into \p pagecount pages (GraphValues) and
|
||||||
|
writes values on given \p page into \p o.
|
||||||
|
\param[out] o: variable to write page into
|
||||||
|
\param[in] page: page to get
|
||||||
|
\param[in] pagecount: number of page to break data into
|
||||||
|
*/
|
||||||
void getPage(GraphValues &o, u32 page, u32 pagecount);
|
void getPage(GraphValues &o, u32 page, u32 pagecount);
|
||||||
|
|
||||||
|
/** \brief Records the \p value in graph entry with given \p id (name) to get
|
||||||
|
exactly this value.
|
||||||
|
\param[in] id: entry name
|
||||||
|
\param[in] value: value to record
|
||||||
|
*/
|
||||||
void graphSet(const std::string &id, float value)
|
void graphSet(const std::string &id, float value)
|
||||||
{
|
{
|
||||||
MutexAutoLock lock(m_mutex);
|
MutexAutoLock lock(m_mutex);
|
||||||
m_graphvalues[id] = value;
|
m_graphvalues[id] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \brief Records the \p value in graph entry with given \p id (name) to get
|
||||||
|
sum of recorded values.
|
||||||
|
\param[in] id: entry name
|
||||||
|
\param[in] value: value to record
|
||||||
|
*/
|
||||||
void graphAdd(const std::string &id, float value)
|
void graphAdd(const std::string &id, float value)
|
||||||
{
|
{
|
||||||
MutexAutoLock lock(m_mutex);
|
MutexAutoLock lock(m_mutex);
|
||||||
@ -72,6 +143,9 @@ class Profiler
|
|||||||
else
|
else
|
||||||
it->second += value;
|
it->second += value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Gives m_graphvalues into \p result.
|
||||||
|
/// \param[out] result: Variable to record values into
|
||||||
void graphPop(GraphValues &result)
|
void graphPop(GraphValues &result)
|
||||||
{
|
{
|
||||||
MutexAutoLock lock(m_mutex);
|
MutexAutoLock lock(m_mutex);
|
||||||
@ -79,6 +153,8 @@ class Profiler
|
|||||||
std::swap(result, m_graphvalues);
|
std::swap(result, m_graphvalues);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Removes entry with given \p name.
|
||||||
|
/// \param[in] name: Name of entry to remove
|
||||||
void remove(const std::string& name)
|
void remove(const std::string& name)
|
||||||
{
|
{
|
||||||
MutexAutoLock lock(m_mutex);
|
MutexAutoLock lock(m_mutex);
|
||||||
@ -87,7 +163,10 @@ class Profiler
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
struct DataPair {
|
struct DataPair {
|
||||||
|
/// Recorded value. Recording method depends on used functions (add/avg/max)
|
||||||
|
/// of profiler.
|
||||||
float value = 0;
|
float value = 0;
|
||||||
|
/// Count of records if "avg" method is used.
|
||||||
int avgcount = 0;
|
int avgcount = 0;
|
||||||
|
|
||||||
inline void reset() {
|
inline void reset() {
|
||||||
@ -102,33 +181,69 @@ class Profiler
|
|||||||
};
|
};
|
||||||
|
|
||||||
std::mutex m_mutex;
|
std::mutex m_mutex;
|
||||||
|
/// All the profiler entries, stored until `clear()` call.
|
||||||
std::map<std::string, DataPair> m_data;
|
std::map<std::string, DataPair> m_data;
|
||||||
|
/// Values for profiler graph collected until next frame draw. Value history
|
||||||
|
/// is stored in `ProfilerGraph`.
|
||||||
std::map<std::string, float> m_graphvalues;
|
std::map<std::string, float> m_graphvalues;
|
||||||
u64 m_start_time;
|
u64 m_start_time;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** \brief Global profiler. User can view its data via in-game profiler menu,
|
||||||
|
graph or "/profiler" command.
|
||||||
|
|
||||||
|
Profiling cycles are managed in Game class:
|
||||||
|
|
||||||
|
- cycle for profiler menu (GameUI::updateProfiler()) is managed in
|
||||||
|
Game::updateProfilers() and lasts for \c profiler_print_interval seconds (user
|
||||||
|
setting) or for 3 seconds if setting is set to 0;
|
||||||
|
|
||||||
|
- cycle for ProfilerGraph is managed in Game::updateProfilerGraphs() and lasts
|
||||||
|
for one frame;
|
||||||
|
*/
|
||||||
|
extern Profiler* g_profiler;
|
||||||
|
|
||||||
|
|
||||||
enum ScopeProfilerType : u8
|
enum ScopeProfilerType : u8
|
||||||
{
|
{
|
||||||
|
/// Record time with Profiler::add() (to get sum of recorded values) at scope end.
|
||||||
SPT_ADD = 1,
|
SPT_ADD = 1,
|
||||||
|
/// Record time with Profiler::avg() (to get average of recorded values) at scope end.
|
||||||
SPT_AVG,
|
SPT_AVG,
|
||||||
|
/// Record time with Profiler::graphAdd() (to get sum of recorded values on
|
||||||
|
/// ProfilerGraph) at scope end.
|
||||||
SPT_GRAPH_ADD,
|
SPT_GRAPH_ADD,
|
||||||
|
/// Record time with Profiler::max() (to get maximum of recorded values) at scope end.
|
||||||
SPT_MAX
|
SPT_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
// Note: this class should be kept lightweight.
|
|
||||||
|
|
||||||
|
/** \brief A class for time measurements. Each created object records time from its
|
||||||
|
construction till scope end.
|
||||||
|
|
||||||
|
Note: this class should be kept lightweight.
|
||||||
|
*/
|
||||||
class ScopeProfiler
|
class ScopeProfiler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
/** \brief Begins measurement until scope end.Result will be recorded to
|
||||||
|
\p name
|
||||||
|
profiling entry in \p profiler (profiling entries are created/deleted automatically).
|
||||||
|
*/
|
||||||
ScopeProfiler(Profiler *profiler, const std::string &name,
|
ScopeProfiler(Profiler *profiler, const std::string &name,
|
||||||
ScopeProfilerType type = SPT_ADD,
|
ScopeProfilerType type = SPT_ADD,
|
||||||
TimePrecision precision = PRECISION_MILLI);
|
TimePrecision precision = PRECISION_MILLI);
|
||||||
|
|
||||||
|
/// Ends measurement and record result in profiler.
|
||||||
~ScopeProfiler();
|
~ScopeProfiler();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Profiler *m_profiler = nullptr;
|
Profiler *m_profiler = nullptr; /// Profiler to record in
|
||||||
std::string m_name;
|
std::string m_name; /// Name of profiler entry to record in
|
||||||
u64 m_time1;
|
u64 m_time1; /// Record start time
|
||||||
ScopeProfilerType m_type;
|
ScopeProfilerType m_type;
|
||||||
TimePrecision m_precision;
|
TimePrecision m_precision;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** \} */
|
||||||
|
Loading…
Reference in New Issue
Block a user