Viewing file: Profile.h (4.25 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
//===- Profile.h - XRay Profile Abstraction -------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // Defines the XRay Profile class representing the latency profile generated by // XRay's profiling mode. // //===----------------------------------------------------------------------===// #ifndef LLVM_XRAY_PROFILE_H #define LLVM_XRAY_PROFILE_H
#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Error.h" #include <list> #include <utility> #include <vector>
namespace llvm { namespace xray {
class Profile;
// We forward declare the Trace type for turning a Trace into a Profile. class Trace;
/// This function will attempt to load an XRay Profiling Mode profile from the /// provided |Filename|. /// /// For any errors encountered in the loading of the profile data from /// |Filename|, this function will return an Error condition appropriately. Expected<Profile> loadProfile(StringRef Filename);
/// This algorithm will merge two Profile instances into a single Profile /// instance, aggregating blocks by Thread ID. Profile mergeProfilesByThread(const Profile &L, const Profile &R);
/// This algorithm will merge two Profile instances into a single Profile /// instance, aggregating blocks by function call stack. Profile mergeProfilesByStack(const Profile &L, const Profile &R);
/// This function takes a Trace and creates a Profile instance from it. Expected<Profile> profileFromTrace(const Trace &T);
/// Profile instances are thread-compatible. class Profile { public: using ThreadID = uint64_t; using PathID = unsigned; using FuncID = int32_t;
struct Data { uint64_t CallCount; uint64_t CumulativeLocalTime; };
struct Block { ThreadID Thread; std::vector<std::pair<PathID, Data>> PathData; };
/// Provides a sequence of function IDs from a previously interned PathID. /// /// Returns an error if |P| had not been interned before into the Profile. /// Expected<std::vector<FuncID>> expandPath(PathID P) const;
/// The stack represented in |P| must be in stack order (leaf to root). This /// will always return the same PathID for |P| that has the same sequence. PathID internPath(ArrayRef<FuncID> P);
/// Appends a fully-formed Block instance into the Profile. /// /// Returns an error condition in the following cases: /// /// - The PathData component of the Block is empty /// Error addBlock(Block &&B);
Profile() = default; ~Profile() = default;
Profile(Profile &&O) noexcept : Blocks(std::move(O.Blocks)), NodeStorage(std::move(O.NodeStorage)), Roots(std::move(O.Roots)), PathIDMap(std::move(O.PathIDMap)), NextID(O.NextID) {}
Profile &operator=(Profile &&O) noexcept { Blocks = std::move(O.Blocks); NodeStorage = std::move(O.NodeStorage); Roots = std::move(O.Roots); PathIDMap = std::move(O.PathIDMap); NextID = O.NextID; return *this; }
Profile(const Profile &); Profile &operator=(const Profile &);
friend void swap(Profile &L, Profile &R) { using std::swap; swap(L.Blocks, R.Blocks); swap(L.NodeStorage, R.NodeStorage); swap(L.Roots, R.Roots); swap(L.PathIDMap, R.PathIDMap); swap(L.NextID, R.NextID); }
private: using BlockList = std::list<Block>;
struct TrieNode { FuncID Func = 0; std::vector<TrieNode *> Callees{}; TrieNode *Caller = nullptr; PathID ID = 0; };
// List of blocks associated with a Profile. BlockList Blocks;
// List of TrieNode elements we've seen. std::list<TrieNode> NodeStorage;
// List of call stack roots. SmallVector<TrieNode *, 4> Roots;
// Reverse mapping between a PathID to a TrieNode*. DenseMap<PathID, TrieNode *> PathIDMap;
// Used to identify paths. PathID NextID = 1;
public: using const_iterator = BlockList::const_iterator; const_iterator begin() const { return Blocks.begin(); } const_iterator end() const { return Blocks.end(); } bool empty() const { return Blocks.empty(); } };
} // namespace xray } // namespace llvm
#endif
|