profile.h
Go to the documentation of this file.
00001 // *****************************************************************************
00002 //
00003 // Copyright (c) 2015, Southwest Research Institute® (SwRI®)
00004 // All rights reserved.
00005 //
00006 // Redistribution and use in source and binary forms, with or without
00007 // modification, are permitted provided that the following conditions are met:
00008 //     * Redistributions of source code must retain the above copyright
00009 //       notice, this list of conditions and the following disclaimer.
00010 //     * Redistributions in binary form must reproduce the above copyright
00011 //       notice, this list of conditions and the following disclaimer in the
00012 //       documentation and/or other materials provided with the distribution.
00013 //     * Neither the name of Southwest Research Institute® (SwRI®) nor the
00014 //       names of its contributors may be used to endorse or promote products
00015 //       derived from this software without specific prior written permission.
00016 //
00017 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020 // ARE DISCLAIMED. IN NO EVENT SHALL Southwest Research Institute® BE LIABLE 
00021 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
00022 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
00023 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
00024 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
00025 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
00026 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00027 // DAMAGE.
00028 //
00029 // *****************************************************************************
00030 
00031 #ifndef SWRI_PROFILER_TOOLS_PROFILE_H_
00032 #define SWRI_PROFILER_TOOLS_PROFILE_H_
00033 
00034 #include <deque>
00035 #include <set>
00036 #include <map>
00037 #include <unordered_map>
00038 
00039 #include <QObject>
00040 #include <QString>
00041 #include <QStringList>
00042 #include <swri_profiler_tools/new_profile_data.h>
00043 
00044 namespace swri_profiler_tools
00045 {
00046 class ProfileDatabase;
00047 
00048 class ProfileEntry
00049 {
00050 
00051  public:
00052   // projected is for internal use in the profiler.  This flag
00053   // indicates that the item's current data was projected from a
00054   // previous data point.  This is used to keep the profile data
00055   // consistent despite missing or late data.  This flag only applies
00056   // to data in measured nodes.
00057   
00058   bool projected;
00059   uint64_t cumulative_call_count;
00060   uint64_t cumulative_inclusive_duration_ns;
00061   uint64_t incremental_inclusive_duration_ns;
00062   uint64_t cumulative_exclusive_duration_ns;
00063   uint64_t incremental_exclusive_duration_ns;
00064   uint64_t incremental_max_duration_ns;
00065 
00066   ProfileEntry()
00067     :
00068     projected(false),
00069     cumulative_call_count(0),
00070     cumulative_inclusive_duration_ns(0),
00071     incremental_inclusive_duration_ns(0),
00072     cumulative_exclusive_duration_ns(0),
00073     incremental_exclusive_duration_ns(0),
00074     incremental_max_duration_ns(0)
00075   {}
00076 };  // class ProfileEntry
00077 
00078 class ProfileNode
00079 {
00080   // This is the node's key within it's profile.  It must be positive
00081   // to be a valid node.
00082   int node_key_;
00083   
00084   // The name of this node.  This is the last element of the path (c
00085   // in a/b/c).
00086   QString name_;
00087 
00088   // The full path of the node in the call tree.  (e.g. a/b/c)
00089   QString path_;
00090 
00091   // Nodes can be either measured or inferred.  Measured nodes have
00092   // their inclusive timing information provided by the profiler.
00093   // These are your typical blocks measured by
00094   // SWRI_PROFILE(). Inferred nodes are nodes that were created to
00095   // fill in the call tree.  These are typically your root node and
00096   // nodes corresponding to ROS namespaces.
00097   bool measured_;
00098 
00099   // The data stored by the node.  The array is managed by the
00100   // profile.  Each element corresponds to a time which is determined
00101   // by the Profile's min_time and max_time.
00102   std::deque<ProfileEntry> data_;
00103 
00104   // The node's depth in the tree.
00105   int depth_;
00106 
00107   // The key of this node's parent node.  This will be invalid
00108   // (negative) for the root node.
00109   int parent_;
00110 
00111   // They node's children, in alphabetical order according to their
00112   // paths.
00113   std::vector<int> children_;
00114 
00115   // The ProfileNode is a "dumb" data storage object with read-only
00116   // access to the rest of the world.  The node is managed and
00117   // manipulated directly by the profile.
00118   friend class Profile;
00119 
00120  public:
00121   ProfileNode() 
00122     :
00123     node_key_(-1),
00124     measured_(false),
00125     depth_(-1),
00126     parent_(-1)
00127   {}
00128   
00129   bool isValid() const { return node_key_ >= 0; }
00130   int nodeKey() const { return node_key_; }
00131   const QString& name() const { return name_; }
00132   const QString& path() const { return path_; }
00133   bool isMeasured() const { return measured_; }
00134   const std::deque<ProfileEntry>& data() const { return data_; }
00135   int depth() const { return depth_; }
00136   int parentKey() const { return parent_; }
00137   const std::vector<int>& childKeys() const { return children_; }
00138   bool hasChildren() const { return !children_.empty(); }
00139 };  // class ProfileNode
00140 
00141 class Profile : public QObject
00142 {
00143   Q_OBJECT;
00144 
00145 
00146   // The key of this profile in the database.  This is negative for
00147   // an invalid profile.
00148   int profile_key_;
00149 
00150   // Name of the profile.  This is initialized by the source and may
00151   // be modified by the user.
00152   QString name_;
00153 
00154   // All node data is stored in dense arrays of the same size.  The
00155   // min_time_s_ and max_time_s_ correspond to the timespan currently
00156   // covered by the array.  They are inclusive and exclusive,
00157   // respectively (index 0 => min_time_s, index size() => max_time_s.
00158   uint64_t min_time_s_;
00159   uint64_t max_time_s_;
00160 
00161   // Nodes are stored in an unordered_map so that we can provide
00162   // persistent keys with fast look ups.  We could use the node's path
00163   // as the key (though we need an adapter hash a QString rather than
00164   // std::string), but they we're constantly hashing very long
00165   // strings.  Instead, we assign a unique integer key when the node
00166   // is added.  This map provides reasonable reverse-lookups.  We
00167   // could actually change nodes_ to a vector or deque and still have
00168   // persistent indices as long as we don't allow nodes to be deleted.
00169   std::map<QString, int> node_key_from_path_;
00170   std::unordered_map<int, ProfileNode> nodes_;
00171 
00172   // The flat index stores all the profile's nodes in alphabetical by
00173   // path order.  Traversing in order corresponds to visiting the call
00174   // tree in a depth-first pattern.
00175   std::vector<int> flat_index_;
00176 
00177   
00178   // The ProfileDatabase is the only place we want to create valid
00179   // profiles.  A valid profile is created by initializing a default
00180   // profile.  Initialization is only allowed to happen once.
00181   friend class ProfileDatabase;
00182   void initialize(int profile_key, const QString &name);
00183 
00184   void expandTimeline(const uint64_t sec);
00185   void addDataToAllNodes(const bool back, const size_t count);
00186 
00187   bool touchNode(const QString &path);
00188 
00189   void storeItemData(std::set<uint64_t> &modified_times,
00190                      const int node_key,
00191                      const NewProfileData &item);
00192   
00193   size_t indexFromSec(const uint64_t secs) const { return secs - min_time_s_; }
00194   uint64_t secFromIndex(const uint64_t index) const { return index + min_time_s_; }
00195 
00196   void rebuildIndices();
00197   void rebuildFlatIndex();
00198   void rebuildTreeIndex();
00199   
00200   void updateDerivedData(size_t index);
00201   void updateDerivedDataInternal(ProfileNode& node, size_t index);
00202 
00203  public:
00204   Profile();
00205   ~Profile();
00206 
00207   void addData(const NewProfileDataVector &data);
00208   const bool isValid() const { return profile_key_ >= 0; }
00209   const int profileKey() const { return profile_key_; }
00210 
00211   const QString& name() const { return name_; }
00212   void setName(const QString &name);
00213 
00214   const ProfileNode& node(int node_key) const;
00215   const ProfileNode& rootNode() const;
00216   const int rootKey() const { return 0; }
00217   const std::vector<int>& nodeKeys() const;
00218   
00219  Q_SIGNALS:
00220   // Emitted when the profile is renamed.
00221   void profileModified(int profile_key);
00222   void nodesAdded(int profile_key);
00223   void dataAdded(int profile_key);  
00224 };  // class Profile
00225 }  // namespace swri_profiler_tools
00226 #endif  // SWRI_PROFILER_TOOLS_PROFILE_H_


swri_profiler_tools
Author(s):
autogenerated on Sat Apr 27 2019 03:08:49