profile.h
Go to the documentation of this file.
1 // *****************************************************************************
2 //
3 // Copyright (c) 2015, Southwest Research Institute® (SwRI®)
4 // All rights reserved.
5 //
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions are met:
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 // * Neither the name of Southwest Research Institute® (SwRI®) nor the
14 // names of its contributors may be used to endorse or promote products
15 // derived from this software without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 // ARE DISCLAIMED. IN NO EVENT SHALL Southwest Research Institute® BE LIABLE
21 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
27 // DAMAGE.
28 //
29 // *****************************************************************************
30 
31 #ifndef SWRI_PROFILER_TOOLS_PROFILE_H_
32 #define SWRI_PROFILER_TOOLS_PROFILE_H_
33 
34 #include <deque>
35 #include <set>
36 #include <map>
37 #include <unordered_map>
38 
39 #include <QObject>
40 #include <QString>
41 #include <QStringList>
43 
44 namespace swri_profiler_tools
45 {
46 class ProfileDatabase;
47 
49 {
50 
51  public:
52  // projected is for internal use in the profiler. This flag
53  // indicates that the item's current data was projected from a
54  // previous data point. This is used to keep the profile data
55  // consistent despite missing or late data. This flag only applies
56  // to data in measured nodes.
57 
58  bool projected;
65 
67  :
68  projected(false),
69  cumulative_call_count(0),
70  cumulative_inclusive_duration_ns(0),
71  incremental_inclusive_duration_ns(0),
72  cumulative_exclusive_duration_ns(0),
73  incremental_exclusive_duration_ns(0),
74  incremental_max_duration_ns(0)
75  {}
76 }; // class ProfileEntry
77 
79 {
80  // This is the node's key within it's profile. It must be positive
81  // to be a valid node.
82  int node_key_;
83 
84  // The name of this node. This is the last element of the path (c
85  // in a/b/c).
86  QString name_;
87 
88  // The full path of the node in the call tree. (e.g. a/b/c)
89  QString path_;
90 
91  // Nodes can be either measured or inferred. Measured nodes have
92  // their inclusive timing information provided by the profiler.
93  // These are your typical blocks measured by
94  // SWRI_PROFILE(). Inferred nodes are nodes that were created to
95  // fill in the call tree. These are typically your root node and
96  // nodes corresponding to ROS namespaces.
97  bool measured_;
98 
99  // The data stored by the node. The array is managed by the
100  // profile. Each element corresponds to a time which is determined
101  // by the Profile's min_time and max_time.
102  std::deque<ProfileEntry> data_;
103 
104  // The node's depth in the tree.
105  int depth_;
106 
107  // The key of this node's parent node. This will be invalid
108  // (negative) for the root node.
109  int parent_;
110 
111  // They node's children, in alphabetical order according to their
112  // paths.
113  std::vector<int> children_;
114 
115  // The ProfileNode is a "dumb" data storage object with read-only
116  // access to the rest of the world. The node is managed and
117  // manipulated directly by the profile.
118  friend class Profile;
119 
120  public:
122  :
123  node_key_(-1),
124  measured_(false),
125  depth_(-1),
126  parent_(-1)
127  {}
128 
129  bool isValid() const { return node_key_ >= 0; }
130  int nodeKey() const { return node_key_; }
131  const QString& name() const { return name_; }
132  const QString& path() const { return path_; }
133  bool isMeasured() const { return measured_; }
134  const std::deque<ProfileEntry>& data() const { return data_; }
135  int depth() const { return depth_; }
136  int parentKey() const { return parent_; }
137  const std::vector<int>& childKeys() const { return children_; }
138  bool hasChildren() const { return !children_.empty(); }
139 }; // class ProfileNode
140 
141 class Profile : public QObject
142 {
143  Q_OBJECT;
144 
145 
146  // The key of this profile in the database. This is negative for
147  // an invalid profile.
148  int profile_key_;
149 
150  // Name of the profile. This is initialized by the source and may
151  // be modified by the user.
152  QString name_;
153 
154  // All node data is stored in dense arrays of the same size. The
155  // min_time_s_ and max_time_s_ correspond to the timespan currently
156  // covered by the array. They are inclusive and exclusive,
157  // respectively (index 0 => min_time_s, index size() => max_time_s.
158  uint64_t min_time_s_;
159  uint64_t max_time_s_;
160 
161  // Nodes are stored in an unordered_map so that we can provide
162  // persistent keys with fast look ups. We could use the node's path
163  // as the key (though we need an adapter hash a QString rather than
164  // std::string), but they we're constantly hashing very long
165  // strings. Instead, we assign a unique integer key when the node
166  // is added. This map provides reasonable reverse-lookups. We
167  // could actually change nodes_ to a vector or deque and still have
168  // persistent indices as long as we don't allow nodes to be deleted.
169  std::map<QString, int> node_key_from_path_;
170  std::unordered_map<int, ProfileNode> nodes_;
171 
172  // The flat index stores all the profile's nodes in alphabetical by
173  // path order. Traversing in order corresponds to visiting the call
174  // tree in a depth-first pattern.
175  std::vector<int> flat_index_;
176 
177 
178  // The ProfileDatabase is the only place we want to create valid
179  // profiles. A valid profile is created by initializing a default
180  // profile. Initialization is only allowed to happen once.
181  friend class ProfileDatabase;
182  void initialize(int profile_key, const QString &name);
183 
184  void expandTimeline(const uint64_t sec);
185  void addDataToAllNodes(const bool back, const size_t count);
186 
187  bool touchNode(const QString &path);
188 
189  void storeItemData(std::set<uint64_t> &modified_times,
190  const int node_key,
191  const NewProfileData &item);
192 
193  size_t indexFromSec(const uint64_t secs) const { return secs - min_time_s_; }
194  uint64_t secFromIndex(const uint64_t index) const { return index + min_time_s_; }
195 
196  void rebuildIndices();
197  void rebuildFlatIndex();
198  void rebuildTreeIndex();
199 
200  void updateDerivedData(size_t index);
201  void updateDerivedDataInternal(ProfileNode& node, size_t index);
202 
203  public:
204  Profile();
205  ~Profile();
206 
207  void addData(const NewProfileDataVector &data);
208  bool isValid() const { return profile_key_ >= 0; }
209  int profileKey() const { return profile_key_; }
210 
211  const QString& name() const { return name_; }
212  void setName(const QString &name);
213 
214  const ProfileNode& node(int node_key) const;
215  const ProfileNode& rootNode() const;
216  int rootKey() const { return 0; }
217  const std::vector<int>& nodeKeys() const;
218 
219  Q_SIGNALS:
220  // Emitted when the profile is renamed.
221  void profileModified(int profile_key);
222  void nodesAdded(int profile_key);
223  void dataAdded(int profile_key);
224 }; // class Profile
225 } // namespace swri_profiler_tools
226 #endif // SWRI_PROFILER_TOOLS_PROFILE_H_
std::unordered_map< int, ProfileNode > nodes_
Definition: profile.h:170
ROSCONSOLE_DECL void initialize()
const std::vector< int > & childKeys() const
Definition: profile.h:137
std::map< QString, int > node_key_from_path_
Definition: profile.h:169
const QString & path() const
Definition: profile.h:132
uint64_t cumulative_exclusive_duration_ns
Definition: profile.h:62
std::vector< int > children_
Definition: profile.h:113
std::vector< NewProfileData > NewProfileDataVector
uint64_t incremental_exclusive_duration_ns
Definition: profile.h:63
const QString & name() const
Definition: profile.h:211
size_t indexFromSec(const uint64_t secs) const
Definition: profile.h:193
const QString & name() const
Definition: profile.h:131
uint64_t secFromIndex(const uint64_t index) const
Definition: profile.h:194
uint64_t cumulative_inclusive_duration_ns
Definition: profile.h:60
std::vector< int > flat_index_
Definition: profile.h:175
uint64_t incremental_inclusive_duration_ns
Definition: profile.h:61
const std::deque< ProfileEntry > & data() const
Definition: profile.h:134
std::deque< ProfileEntry > data_
Definition: profile.h:102


swri_profiler_tools
Author(s):
autogenerated on Fri Nov 27 2020 03:44:18