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