diff options
Diffstat (limited to 'clang-r353983/include/llvm/XRay/Profile.h')
| -rw-r--r-- | clang-r353983/include/llvm/XRay/Profile.h | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/clang-r353983/include/llvm/XRay/Profile.h b/clang-r353983/include/llvm/XRay/Profile.h new file mode 100644 index 00000000..79d9b533 --- /dev/null +++ b/clang-r353983/include/llvm/XRay/Profile.h @@ -0,0 +1,149 @@ +//===- 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 |
