Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. //===- Profile.h - XRay Profile Abstraction -------------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // Defines the XRay Profile class representing the latency profile generated by
  10. // XRay's profiling mode.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #ifndef LLVM_XRAY_PROFILE_H
  14. #define LLVM_XRAY_PROFILE_H
  15.  
  16. #include "llvm/ADT/DenseMap.h"
  17. #include "llvm/ADT/SmallVector.h"
  18. #include "llvm/ADT/StringRef.h"
  19. #include "llvm/Support/Error.h"
  20. #include <list>
  21. #include <utility>
  22. #include <vector>
  23.  
  24. namespace llvm {
  25. namespace xray {
  26.  
  27. class Profile;
  28.  
  29. // We forward declare the Trace type for turning a Trace into a Profile.
  30. class Trace;
  31.  
  32. /// This function will attempt to load an XRay Profiling Mode profile from the
  33. /// provided |Filename|.
  34. ///
  35. /// For any errors encountered in the loading of the profile data from
  36. /// |Filename|, this function will return an Error condition appropriately.
  37. Expected<Profile> loadProfile(StringRef Filename);
  38.  
  39. /// This algorithm will merge two Profile instances into a single Profile
  40. /// instance, aggregating blocks by Thread ID.
  41. Profile mergeProfilesByThread(const Profile &L, const Profile &R);
  42.  
  43. /// This algorithm will merge two Profile instances into a single Profile
  44. /// instance, aggregating blocks by function call stack.
  45. Profile mergeProfilesByStack(const Profile &L, const Profile &R);
  46.  
  47. /// This function takes a Trace and creates a Profile instance from it.
  48. Expected<Profile> profileFromTrace(const Trace &T);
  49.  
  50. /// Profile instances are thread-compatible.
  51. class Profile {
  52. public:
  53.   using ThreadID = uint64_t;
  54.   using PathID = unsigned;
  55.   using FuncID = int32_t;
  56.  
  57.   struct Data {
  58.     uint64_t CallCount;
  59.     uint64_t CumulativeLocalTime;
  60.   };
  61.  
  62.   struct Block {
  63.     ThreadID Thread;
  64.     std::vector<std::pair<PathID, Data>> PathData;
  65.   };
  66.  
  67.   /// Provides a sequence of function IDs from a previously interned PathID.
  68.   ///
  69.   /// Returns an error if |P| had not been interned before into the Profile.
  70.   ///
  71.   Expected<std::vector<FuncID>> expandPath(PathID P) const;
  72.  
  73.   /// The stack represented in |P| must be in stack order (leaf to root). This
  74.   /// will always return the same PathID for |P| that has the same sequence.
  75.   PathID internPath(ArrayRef<FuncID> P);
  76.  
  77.   /// Appends a fully-formed Block instance into the Profile.
  78.   ///
  79.   /// Returns an error condition in the following cases:
  80.   ///
  81.   ///    - The PathData component of the Block is empty
  82.   ///
  83.   Error addBlock(Block &&B);
  84.  
  85.   Profile() = default;
  86.   ~Profile() = default;
  87.  
  88.   Profile(Profile &&O) noexcept
  89.       : Blocks(std::move(O.Blocks)), NodeStorage(std::move(O.NodeStorage)),
  90.         Roots(std::move(O.Roots)), PathIDMap(std::move(O.PathIDMap)),
  91.         NextID(O.NextID) {}
  92.  
  93.   Profile &operator=(Profile &&O) noexcept {
  94.     Blocks = std::move(O.Blocks);
  95.     NodeStorage = std::move(O.NodeStorage);
  96.     Roots = std::move(O.Roots);
  97.     PathIDMap = std::move(O.PathIDMap);
  98.     NextID = O.NextID;
  99.     return *this;
  100.   }
  101.  
  102.   Profile(const Profile &);
  103.   Profile &operator=(const Profile &);
  104.  
  105.   friend void swap(Profile &L, Profile &R) {
  106.     using std::swap;
  107.     swap(L.Blocks, R.Blocks);
  108.     swap(L.NodeStorage, R.NodeStorage);
  109.     swap(L.Roots, R.Roots);
  110.     swap(L.PathIDMap, R.PathIDMap);
  111.     swap(L.NextID, R.NextID);
  112.   }
  113.  
  114. private:
  115.   using BlockList = std::list<Block>;
  116.  
  117.   struct TrieNode {
  118.     FuncID Func = 0;
  119.     std::vector<TrieNode *> Callees{};
  120.     TrieNode *Caller = nullptr;
  121.     PathID ID = 0;
  122.   };
  123.  
  124.   // List of blocks associated with a Profile.
  125.   BlockList Blocks;
  126.  
  127.   // List of TrieNode elements we've seen.
  128.   std::list<TrieNode> NodeStorage;
  129.  
  130.   // List of call stack roots.
  131.   SmallVector<TrieNode *, 4> Roots;
  132.  
  133.   // Reverse mapping between a PathID to a TrieNode*.
  134.   DenseMap<PathID, TrieNode *> PathIDMap;
  135.  
  136.   // Used to identify paths.
  137.   PathID NextID = 1;
  138.  
  139. public:
  140.   using const_iterator = BlockList::const_iterator;
  141.   const_iterator begin() const { return Blocks.begin(); }
  142.   const_iterator end() const { return Blocks.end(); }
  143.   bool empty() const { return Blocks.empty(); }
  144. };
  145.  
  146. } // namespace xray
  147. } // namespace llvm
  148.  
  149. #endif
  150.