From 7be7d15a02ef34aa8eebe3b78c75be0737e2b246 Mon Sep 17 00:00:00 2001 From: ZavGaro Date: Sat, 15 Jun 2024 13:37:06 +0300 Subject: [PATCH 1/5] Add documentation to profiler and profiler graph --- src/gui/profilergraph.h | 4 +++ src/profiler.h | 66 ++++++++++++++++++++++++++++++++++++++--- 2 files changed, 66 insertions(+), 4 deletions(-) diff --git a/src/gui/profilergraph.h b/src/gui/profilergraph.h index 6354ac9ef..186304468 100644 --- a/src/gui/profilergraph.h +++ b/src/gui/profilergraph.h @@ -30,11 +30,13 @@ with this program; if not, write to the Free Software Foundation, Inc., class ProfilerGraph { private: + // One-frame slice of graph values. struct Piece { Piece(Profiler::GraphValues v) : values(std::move(v)) {} Profiler::GraphValues values; }; + // Data for drawing a one graph. Updates every frame. struct Meta { float min; @@ -54,6 +56,8 @@ class ProfilerGraph 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 draw(s32 x_left, s32 y_bottom, video::IVideoDriver *driver, diff --git a/src/profiler.h b/src/profiler.h index e7135d9c2..3e28b8e24 100644 --- a/src/profiler.h +++ b/src/profiler.h @@ -29,21 +29,55 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "util/timetaker.h" #include "util/numeric.h" // paging() -// Global profiler class Profiler; +// Global profiler. Its data is available for user. extern Profiler *g_profiler; /* Time profiler -*/ + Collects data (time intervals and other) in two independent cycles. + + - Cycle for profiler graph lasts for one frame and managed in + `Game::updateProfilerGraphs()`, result is displayed by `ProfilerGraph`. + + - Cycle for all other data lasts for `profiler_print_interval` seconds (user + setting) and managed in `Game::updateProfilers()`, result is given in text + form by `print` function. User can view it via in-game profiler menu or + "/profiler" command. + + All data is cleared at cycle end. +*/ class Profiler { public: Profiler(); + /* + Adds value to given profiler entry (`name`). Does not change count + in the entry. + + As a resut, profiler will give *sum* of record values as value and "1" as avgCount. + (If only this method is used for given entry between profiler updates) + */ void add(const std::string &name, float value); + + /* + Adds value to given profiler entry (`name`) and increases its record count + by 1. + + As a resut, profiler will give *average* of record vaues as value and count of + records as avgCount. + (If only this method is used for given entry between profiler updates) + */ void avg(const std::string &name, float value); + /* + Sets value to given profiler entry (`name`) if it is larger then existing one and + increases record coutn by 1. + + As a resut, profiler will give *max* record value as value and count of records as avgCount. + (If only this method is used for given entry between profiler updates) + */ void max(const std::string &name, float value); void clear(); @@ -55,6 +89,7 @@ class Profiler // Returns the line count int print(std::ostream &o, u32 page = 1, u32 pagecount = 1); + // Writes values on page into `o`. void getPage(GraphValues &o, u32 page, u32 pagecount); @@ -87,7 +122,10 @@ class Profiler private: struct DataPair { + // Recorded value. Recording method depends on used functions (add/avg/max) + // of profiler float value = 0; + // Count of records. int avgcount = 0; inline void reset() { @@ -102,33 +140,53 @@ class Profiler }; std::mutex m_mutex; + // All the profiler entries, stored untill `clear()` call. std::map m_data; + // Values for profiler graph collected untill next frame draw. Value history + // are stored in `ProfilerGraph`. std::map m_graphvalues; u64 m_start_time; }; + enum ScopeProfilerType : u8 { + // Accumulate measurements untill profiler update. + // Profiler will print sum as value and "1" as count. SPT_ADD = 1, + // Accumulate measurements and record count untill profiler update. + // Profiler will print average value as value and record count as count. SPT_AVG, + // Accumulate measurements until frame update and then add sum to profiler graph. SPT_GRAPH_ADD, + // Save only the largest recorded value. Profiler will print them as value and "1" as count. SPT_MAX }; -// Note: this class should be kept lightweight. +/* + 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 { public: + /* + Begins record untill scope end. Result will be added to `name` profiling + entry in `profiler` (profiling entries are created/deleted automatically). + */ ScopeProfiler(Profiler *profiler, const std::string &name, ScopeProfilerType type = SPT_ADD, TimePrecision precision = PRECISION_MILLI); + + // Ends record and logs result in profiler. ~ScopeProfiler(); private: Profiler *m_profiler = nullptr; std::string m_name; - u64 m_time1; + u64 m_time1; // Record start time ScopeProfilerType m_type; TimePrecision m_precision; }; From e41e2c43e8d8f9dc34a82204077ce130c42945c9 Mon Sep 17 00:00:00 2001 From: ZavGaro Date: Mon, 24 Jun 2024 21:23:58 +0300 Subject: [PATCH 2/5] Add documentation to Profiler and ProfilerGraph in Doxygen format --- src/gui/profilergraph.h | 19 +++-- src/profiler.h | 167 +++++++++++++++++++++++++++------------- 2 files changed, 127 insertions(+), 59 deletions(-) diff --git a/src/gui/profilergraph.h b/src/gui/profilergraph.h index 186304468..ef33d797d 100644 --- a/src/gui/profilergraph.h +++ b/src/gui/profilergraph.h @@ -26,17 +26,26 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include "profiler.h" -/* Profiler display */ + +/** \brief Draws graph every frame using data given by Profiler. + + It displays only entries that 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 graph value, entry name and lower graph + 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. +*/ class ProfilerGraph { private: - // One-frame slice of graph values. + /// One-frame slice of graph values. struct Piece { Piece(Profiler::GraphValues v) : values(std::move(v)) {} Profiler::GraphValues values; }; - // Data for drawing a one graph. Updates every frame. + /// Data for drawing one graph. Updates every frame. struct Meta { float min; @@ -56,8 +65,8 @@ class ProfilerGraph 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`). + /// 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 draw(s32 x_left, s32 y_bottom, video::IVideoDriver *driver, diff --git a/src/profiler.h b/src/profiler.h index 3e28b8e24..06939d2b0 100644 --- a/src/profiler.h +++ b/src/profiler.h @@ -29,56 +29,63 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "util/timetaker.h" #include "util/numeric.h" // paging() -class Profiler; -// Global profiler. Its data is available for user. -extern Profiler *g_profiler; -/* - Time profiler +/** \defgroup Profiling Profiling tools + \brief In-engine tools to profile CPU time or everything else that is recorded + in by special functions. - Collects data (time intervals and other) in two independent cycles. + Usage 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. - - Cycle for profiler graph lasts for one frame and managed in - `Game::updateProfilerGraphs()`, result is displayed by `ProfilerGraph`. + TimeTaker can be used instead of ScopeProfiler. + \{ +*/ - - Cycle for all other data lasts for `profiler_print_interval` seconds (user - setting) and managed in `Game::updateProfilers()`, result is given in text - form by `print` function. User can view it via in-game profiler menu or - "/profiler" command. - All data is cleared at cycle end. +/** \brief Collects values (time intervals, counts and other) in named entries. + + Can be used to get sum, average or maximum of recoeded 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 { public: Profiler(); - /* - Adds value to given profiler entry (`name`). Does not change count - in the entry. - - As a resut, profiler will give *sum* of record values as value and "1" as avgCount. - (If only this method is used for given entry between profiler updates) + /** \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); - /* - Adds value to given profiler entry (`name`) and increases its record count - by 1. - - As a resut, profiler will give *average* of record vaues as value and count of - records as avgCount. - (If only this method is used for given entry between profiler updates) + /** \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); - /* - Sets value to given profiler entry (`name`) if it is larger then existing one and - increases record coutn by 1. - As a resut, profiler will give *max* record value as value and count of records as avgCount. - (If only this method is used for given entry between profiler updates) + /** \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); + + /// Clears all profiling entries (#m_data). Does not affect #m_graphvalues. void clear(); float getValue(const std::string &name) const; @@ -87,17 +94,46 @@ class Profiler typedef std::map 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); - // Writes values on page into `o`. + + /** \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); - + /** \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) { MutexAutoLock lock(m_mutex); 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) { MutexAutoLock lock(m_mutex); @@ -107,6 +143,9 @@ class Profiler else it->second += value; } + + /// \brief Gives m_graphvalues into \p result. + /// \param[out] result: Variable to record values into void graphPop(GraphValues &result) { MutexAutoLock lock(m_mutex); @@ -114,6 +153,8 @@ class Profiler 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) { MutexAutoLock lock(m_mutex); @@ -122,10 +163,10 @@ class Profiler private: struct DataPair { - // Recorded value. Recording method depends on used functions (add/avg/max) - // of profiler + /// Recorded value. Recording method depends on used functions (add/avg/max) + /// of profiler. float value = 0; - // Count of records. + /// Count of records if "avg" method is used. int avgcount = 0; inline void reset() { @@ -140,31 +181,49 @@ class Profiler }; std::mutex m_mutex; - // All the profiler entries, stored untill `clear()` call. + /// All the profiler entries, stored untill `clear()` call. std::map m_data; - // Values for profiler graph collected untill next frame draw. Value history - // are stored in `ProfilerGraph`. + /// Values for profiler graph collected untill next frame draw. Value history + /// is stored in `ProfilerGraph`. std::map m_graphvalues; u64 m_start_time; }; +/** \brief Global profiler. User can view its data via in-game profiler menu, + graph or "/profiler" command. + + It collects data for + - itself, in Game::updateProfilers(); result is given in text form by print() + (user can view it via in-game profiler menu or "/profiler" command); + + - profiler graph, in Game::updateProfilerGraphs(); result is displayed by + ProfilerGraph. + + Cycle for profiler graph data lasts for one frame. Cycle for all other data lasts + for \c profiler_print_interval seconds (user setting) or for 3 seconds if setting + is setted to 0, and managed in Game::updateProfilers(). + + All corresponding data is cleared at cycle end. +*/ +extern Profiler* g_profiler; + + enum ScopeProfilerType : u8 { - // Accumulate measurements untill profiler update. - // Profiler will print sum as value and "1" as count. + /// Record time with Profiler::add() (to get sum of recorded values) at scope end. SPT_ADD = 1, - // Accumulate measurements and record count untill profiler update. - // Profiler will print average value as value and record count as count. + /// Record time with Profiler::avg() (to get average of recorded values) at scope end. SPT_AVG, - // Accumulate measurements until frame update and then add sum to profiler graph. + /// Record time with Profiler::graphAdd() (to get get sum of recorded values on + /// ProfilerGraph) at scope end. SPT_GRAPH_ADD, - // Save only the largest recorded value. Profiler will print them as value and "1" as count. + /// Record time with Profiler::max() (to get maximum of recorded values) at scope end. SPT_MAX }; -/* - A class for time measurements. Each created object records time from its + +/** \brief A class for time measurements. Each created object records time from its construction till scope end. Note: this class should be kept lightweight. @@ -172,21 +231,21 @@ enum ScopeProfilerType : u8 class ScopeProfiler { public: - /* - Begins record untill scope end. Result will be added to `name` profiling - entry in `profiler` (profiling entries are created/deleted automatically). - */ + /// \brief Begins record untill scope end. Result will be added to \p name profiling + /// entry in \p profiler (profiling entries are created/deleted automatically). ScopeProfiler(Profiler *profiler, const std::string &name, ScopeProfilerType type = SPT_ADD, TimePrecision precision = PRECISION_MILLI); - // Ends record and logs result in profiler. + /// Ends record and logs result in profiler. ~ScopeProfiler(); private: Profiler *m_profiler = nullptr; std::string m_name; - u64 m_time1; // Record start time + u64 m_time1; /// Record start time ScopeProfilerType m_type; TimePrecision m_precision; }; + +/** \} */ From 4dc3fd2fcc01099e015dbd968012bdb3ba20b5b3 Mon Sep 17 00:00:00 2001 From: ZavGaro Date: Tue, 25 Jun 2024 16:15:11 +0300 Subject: [PATCH 3/5] Improve Profiler documentation --- src/profiler.h | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/src/profiler.h b/src/profiler.h index 06939d2b0..2d7d1edd2 100644 --- a/src/profiler.h +++ b/src/profiler.h @@ -31,10 +31,10 @@ with this program; if not, write to the Free Software Foundation, Inc., /** \defgroup Profiling Profiling tools - \brief In-engine tools to profile CPU time or everything else that is recorded - in by special functions. + \brief Embedded tools to profile CPU time or anything else that is recorded + by certain functions. - Usage example with global profiler (#g_profiler), that is available in any file + An example with global profiler (#g_profiler), that is available in any file with profiler.h included: \code{.c++} void functionToProfie(int count) { @@ -193,18 +193,14 @@ class Profiler /** \brief Global profiler. User can view its data via in-game profiler menu, graph or "/profiler" command. - It collects data for - - itself, in Game::updateProfilers(); result is given in text form by print() - (user can view it via in-game profiler menu or "/profiler" command); + Profiling cycles are managed in Game class: - - profiler graph, in Game::updateProfilerGraphs(); result is displayed by - ProfilerGraph. + - 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 setted to 0; - Cycle for profiler graph data lasts for one frame. Cycle for all other data lasts - for \c profiler_print_interval seconds (user setting) or for 3 seconds if setting - is setted to 0, and managed in Game::updateProfilers(). - - All corresponding data is cleared at cycle end. + - cycle for ProfilerGraph is managed in Game::updateProfilerGraphs() and lasts + for one frame; */ extern Profiler* g_profiler; @@ -231,19 +227,21 @@ enum ScopeProfilerType : u8 class ScopeProfiler { public: - /// \brief Begins record untill scope end. Result will be added to \p name profiling - /// entry in \p profiler (profiling entries are created/deleted automatically). + /** \brief Begins measurement untill 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, ScopeProfilerType type = SPT_ADD, TimePrecision precision = PRECISION_MILLI); - /// Ends record and logs result in profiler. + /// Ends measurement and record result in profiler. ~ScopeProfiler(); private: - Profiler *m_profiler = nullptr; - std::string m_name; - u64 m_time1; /// Record start time + Profiler *m_profiler = nullptr; /// Profiler to record in + std::string m_name; /// Name of profiler entry to record in + u64 m_time1; /// Record start time ScopeProfilerType m_type; TimePrecision m_precision; }; From 31337a04861e7eb57f52ad87c97529ac2db97556 Mon Sep 17 00:00:00 2001 From: ZavGaro Date: Tue, 25 Jun 2024 16:25:17 +0300 Subject: [PATCH 4/5] Correct ProfilerGraph documentation --- src/gui/profilergraph.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/gui/profilergraph.h b/src/gui/profilergraph.h index ef33d797d..1563d3c48 100644 --- a/src/gui/profilergraph.h +++ b/src/gui/profilergraph.h @@ -29,12 +29,14 @@ with this program; if not, write to the Free Software Foundation, Inc., /** \brief Draws graph every frame using data given by Profiler. - It displays only entries that recorded for profiler graph (via Profiler::graphAdd, + 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 graph value, entry name and lower graph + 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 { From be6c00d1b4d0fe630371939396c9e077db294223 Mon Sep 17 00:00:00 2001 From: ZavGaro Date: Tue, 25 Jun 2024 16:51:12 +0300 Subject: [PATCH 5/5] Grammatical corrections in Profiler and ProfilerGraph documentation --- src/profiler.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/profiler.h b/src/profiler.h index 2d7d1edd2..9ce055a1a 100644 --- a/src/profiler.h +++ b/src/profiler.h @@ -55,7 +55,7 @@ with this program; if not, write to the Free Software Foundation, Inc., /** \brief Collects values (time intervals, counts and other) in named entries. - Can be used to get sum, average or maximum of recoeded values for each entry. Gives + 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(). @@ -181,9 +181,9 @@ class Profiler }; std::mutex m_mutex; - /// All the profiler entries, stored untill `clear()` call. + /// All the profiler entries, stored until `clear()` call. std::map m_data; - /// Values for profiler graph collected untill next frame draw. Value history + /// Values for profiler graph collected until next frame draw. Value history /// is stored in `ProfilerGraph`. std::map m_graphvalues; u64 m_start_time; @@ -197,7 +197,7 @@ class Profiler - 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 setted to 0; + setting) or for 3 seconds if setting is set to 0; - cycle for ProfilerGraph is managed in Game::updateProfilerGraphs() and lasts for one frame; @@ -211,7 +211,7 @@ enum ScopeProfilerType : u8 SPT_ADD = 1, /// Record time with Profiler::avg() (to get average of recorded values) at scope end. SPT_AVG, - /// Record time with Profiler::graphAdd() (to get get sum of recorded values on + /// Record time with Profiler::graphAdd() (to get sum of recorded values on /// ProfilerGraph) at scope end. SPT_GRAPH_ADD, /// Record time with Profiler::max() (to get maximum of recorded values) at scope end. @@ -227,7 +227,7 @@ enum ScopeProfilerType : u8 class ScopeProfiler { public: - /** \brief Begins measurement untill scope end.Result will be recorded to + /** \brief Begins measurement until scope end.Result will be recorded to \p name profiling entry in \p profiler (profiling entries are created/deleted automatically). */