mirror of
https://github.com/yse/easy_profiler.git
synced 2025-01-14 00:27:55 +08:00
(profiler reader) Added calculation of maximum depth of the BlocksTree;
* Also added header into reader.cpp and added comments.
This commit is contained in:
parent
2939f07c2a
commit
8b4bd91147
@ -97,8 +97,9 @@ struct BlocksTree
|
||||
::profiler::BlockStatistics* frame_statistics; ///< Pointer to statistics for this block within the parent (may be nullptr for top-level blocks)
|
||||
::profiler::BlockStatistics* total_statistics; ///< Pointer to statistics for this block within the bounds of all frames per current thread
|
||||
unsigned int total_children_number; ///< Number of all children including number of grandchildren (and so on)
|
||||
unsigned short sublevels; ///< Maximum number of sublevels (maximum children depth)
|
||||
|
||||
BlocksTree() : node(nullptr), frame_statistics(nullptr), total_statistics(nullptr), total_children_number(0)
|
||||
BlocksTree() : node(nullptr), frame_statistics(nullptr), total_statistics(nullptr), total_children_number(0), sublevels(0)
|
||||
{
|
||||
|
||||
}
|
||||
@ -158,6 +159,7 @@ private:
|
||||
frame_statistics = that.frame_statistics;
|
||||
total_statistics = that.total_statistics;
|
||||
total_children_number = that.total_children_number;
|
||||
sublevels = that.sublevels;
|
||||
|
||||
that.node = nullptr;
|
||||
that.frame_statistics = nullptr;
|
||||
|
107
src/reader.cpp
107
src/reader.cpp
@ -1,3 +1,34 @@
|
||||
/************************************************************************
|
||||
* file name : reader.cpp
|
||||
* ----------------- :
|
||||
* creation time : 2016/06/19
|
||||
* copyright : (c) 2016 Sergey Yagovtsev, Victor Zarubkin
|
||||
* authors : Sergey Yagovtsev, Victor Zarubkin
|
||||
* emails : yse.sey@gmail.com, v.s.zarubkin@gmail.com
|
||||
* ----------------- :
|
||||
* description : The file contains implementation of fillTreesFromFile function
|
||||
* : which reads profiler file and fill profiler blocks tree.
|
||||
* ----------------- :
|
||||
* change log : * 2016/06/19 Sergey Yagovtsev: First fillTreesFromFile implementation.
|
||||
* :
|
||||
* : * 2016/06/25 Victor Zarubkin: Removed unnecessary memory allocation and copy
|
||||
* : when creating and inserting blocks into the tree.
|
||||
* :
|
||||
* : * 2016/06/26 Victor Zarubkin: Added statistics gathering (min, max, average duration,
|
||||
* : number of block calls).
|
||||
* : * 2016/06/26 Victor Zarubkin, Sergey Yagovtsev: Added statistics gathering for root
|
||||
* : blocks in the tree.
|
||||
* :
|
||||
* : * 2016/06/29 Victor Zarubkin: Added calculaton of total children number for blocks.
|
||||
* :
|
||||
* : * 2016/06/30 Victor Zarubkin: Added this header.
|
||||
* : Added tree depth calculation.
|
||||
* :
|
||||
* : *
|
||||
* ----------------- :
|
||||
* license : TODO: add license text
|
||||
************************************************************************/
|
||||
|
||||
#include "profiler/reader.h"
|
||||
#include <fstream>
|
||||
#include <iterator>
|
||||
@ -8,6 +39,17 @@
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
/** \brief Simple C-string pointer with length.
|
||||
|
||||
It is used as base class for a key in std::unordered_map.
|
||||
It is used to get better performance than std::string.
|
||||
It simply stores a pointer and a length, there is no
|
||||
any memory allocation and copy.
|
||||
|
||||
\note It is absolutely safe to store pointer because std::unordered_map,
|
||||
which uses it as a key, exists only inside fillTreesFromFile function.
|
||||
|
||||
*/
|
||||
class cstring
|
||||
{
|
||||
protected:
|
||||
@ -46,6 +88,14 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/** \brief cstring with precalculated hash.
|
||||
|
||||
This is used to calculate hash for C-string and to cache it
|
||||
to be used in the future without recurring hash calculatoin.
|
||||
|
||||
\note This class is used as a key in std::unordered_map.
|
||||
|
||||
*/
|
||||
class hashed_cstr : public cstring
|
||||
{
|
||||
typedef cstring Parent;
|
||||
@ -76,6 +126,7 @@ public:
|
||||
|
||||
namespace std {
|
||||
|
||||
/** \brief Simply returns precalculated hash of a C-string. */
|
||||
template <>
|
||||
struct hash<hashed_cstr>
|
||||
{
|
||||
@ -99,6 +150,18 @@ typedef ::std::unordered_map<::std::string, ::profiler::BlockStatistics*> StatsM
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/** \brief Updates statistics for a profiler block.
|
||||
|
||||
\param _stats_map Storage of statistics for blocks.
|
||||
\param _current Pointer to the current block.
|
||||
\param _stats Reference to the variable where pointer to the block statistics must be written.
|
||||
|
||||
\note All blocks with similar name have the same pointer to statistics information.
|
||||
|
||||
\note As all profiler block keeps a pointer to it's statistics, all similar blocks
|
||||
automatically receive statistics update.
|
||||
|
||||
*/
|
||||
void update_statistics(StatsMap& _stats_map, ::profiler::SerilizedBlock* _current, ::profiler::BlockStatistics*& _stats)
|
||||
{
|
||||
auto duration = _current->block()->duration();
|
||||
@ -106,14 +169,17 @@ void update_statistics(StatsMap& _stats_map, ::profiler::SerilizedBlock* _curren
|
||||
auto it = _stats_map.find(key);
|
||||
if (it != _stats_map.end())
|
||||
{
|
||||
_stats = it->second;
|
||||
// Update already existing statistics
|
||||
|
||||
++_stats->calls_number;
|
||||
_stats->total_duration += duration;
|
||||
_stats = it->second; // write pointer to statistics into output (this is BlocksTree::total_statistics or BlocksTree::frame_statistics)
|
||||
|
||||
++_stats->calls_number; // update calls number of this block
|
||||
_stats->total_duration += duration; // update summary duration of all block calls
|
||||
|
||||
//if (duration > _stats->max_duration_block->block()->duration())
|
||||
if (duration > _stats->max_duration)
|
||||
{
|
||||
// update max duration
|
||||
_stats->max_duration_block = _current;
|
||||
_stats->max_duration = duration;
|
||||
}
|
||||
@ -121,12 +187,17 @@ void update_statistics(StatsMap& _stats_map, ::profiler::SerilizedBlock* _curren
|
||||
//if (duration < _stats->min_duration_block->block()->duration())
|
||||
if (duration < _stats->min_duration)
|
||||
{
|
||||
// update min duraton
|
||||
_stats->min_duration_block = _current;
|
||||
_stats->min_duration = duration;
|
||||
}
|
||||
|
||||
// average duration is calculated inside average_duration() method by dividing total_duration to the calls_number
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is first time the block appear in the file.
|
||||
// Create new statistics.
|
||||
_stats = new ::profiler::BlockStatistics(duration, _current);
|
||||
_stats_map.insert(::std::make_pair(key, _stats));
|
||||
}
|
||||
@ -192,9 +263,12 @@ extern "C"{
|
||||
{
|
||||
tree.total_children_number += child.total_children_number;
|
||||
update_statistics(frame_statistics, child.node, child.frame_statistics);
|
||||
if (tree.sublevels < child.sublevels)
|
||||
tree.sublevels = child.sublevels;
|
||||
}
|
||||
|
||||
tree.total_children_number += static_cast<unsigned int>(tree.children.size());
|
||||
++tree.sublevels;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -216,30 +290,39 @@ extern "C"{
|
||||
|
||||
if (gather_statistics)
|
||||
{
|
||||
for (auto& root : threaded_trees)
|
||||
for (auto& root_value : threaded_trees)
|
||||
{
|
||||
auto& root = root_value.second;
|
||||
|
||||
frame_statistics.clear();
|
||||
for (auto& frame : root.second.children)
|
||||
for (auto& frame : root.children)
|
||||
{
|
||||
root.second.total_children_number += frame.total_children_number;
|
||||
root.total_children_number += frame.total_children_number;
|
||||
update_statistics(frame_statistics, frame.node, frame.frame_statistics);
|
||||
if (root.sublevels < frame.sublevels)
|
||||
root.sublevels = frame.sublevels;
|
||||
}
|
||||
root.second.total_children_number += static_cast<unsigned int>(root.second.children.size());
|
||||
root.total_children_number += static_cast<unsigned int>(root.children.size());
|
||||
++root.sublevels;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto& root : threaded_trees)
|
||||
for (auto& root_value : threaded_trees)
|
||||
{
|
||||
for (auto& frame : root.second.children)
|
||||
auto& root = root_value.second;
|
||||
for (auto& frame : root.children)
|
||||
{
|
||||
root.second.total_children_number += frame.total_children_number;
|
||||
root.total_children_number += frame.total_children_number;
|
||||
if (root.sublevels < frame.sublevels)
|
||||
root.sublevels = frame.sublevels;
|
||||
}
|
||||
root.second.total_children_number += static_cast<unsigned int>(root.second.children.size());
|
||||
root.total_children_number += static_cast<unsigned int>(root.children.size());
|
||||
++root.sublevels;
|
||||
}
|
||||
}
|
||||
|
||||
// No need to delete BlockStatistics instances - they will be deleted on BlocksTree destructors
|
||||
// No need to delete BlockStatistics instances - they will be deleted inside BlocksTree destructors
|
||||
|
||||
return blocks_counter;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user