Path: blob/main/contrib/llvm-project/llvm/tools/llvm-xray/xray-graph.h
35230 views
//===-- xray-graph.h - XRay Function Call Graph Renderer --------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// Generate a DOT file to represent the function call graph encountered in9// the trace.10//11//===----------------------------------------------------------------------===//1213#ifndef XRAY_GRAPH_H14#define XRAY_GRAPH_H1516#include <string>17#include <vector>1819#include "func-id-helper.h"20#include "xray-color-helper.h"21#include "llvm/ADT/DenseMap.h"22#include "llvm/ADT/SmallVector.h"23#include "llvm/Support/Errc.h"24#include "llvm/Support/Program.h"25#include "llvm/Support/raw_ostream.h"26#include "llvm/XRay/Graph.h"27#include "llvm/XRay/Trace.h"28#include "llvm/XRay/XRayRecord.h"2930namespace llvm {31namespace xray {3233/// A class encapsulating the logic related to analyzing XRay traces, producting34/// Graphs from them and then exporting those graphs for review.35class GraphRenderer {36public:37/// An enum for enumerating the various statistics gathered on latencies38enum class StatType { NONE, COUNT, MIN, MED, PCT90, PCT99, MAX, SUM };3940/// An inner struct for common timing statistics information41struct TimeStat {42int64_t Count;43double Min;44double Median;45double Pct90;46double Pct99;47double Max;48double Sum;4950std::string getString(StatType T) const;51double getDouble(StatType T) const;52};53using TimestampT = uint64_t;5455/// An inner struct for storing edge attributes for our graph. Here the56/// attributes are mainly function call statistics.57///58/// FIXME: expand to contain more information eg call latencies.59struct CallStats {60TimeStat S;61std::vector<TimestampT> Timings;62};6364/// An Inner Struct for storing vertex attributes, at the moment just65/// SymbolNames, however in future we could store bulk function statistics.66///67/// FIXME: Store more attributes based on instrumentation map.68struct FunctionStats {69std::string SymbolName;70TimeStat S = {};71};7273struct FunctionAttr {74int32_t FuncId;75uint64_t TSC;76};7778using FunctionStack = SmallVector<FunctionAttr, 4>;7980using PerThreadFunctionStackMap = DenseMap<uint32_t, FunctionStack>;8182class GraphT : public Graph<FunctionStats, CallStats, int32_t> {83public:84TimeStat GraphEdgeMax = {};85TimeStat GraphVertexMax = {};86};8788GraphT G;89using VertexIdentifier = typename decltype(G)::VertexIdentifier;90using EdgeIdentifier = decltype(G)::EdgeIdentifier;9192/// Use a Map to store the Function stack for each thread whilst building the93/// graph.94///95/// FIXME: Perhaps we can Build this into LatencyAccountant? or vise versa?96PerThreadFunctionStackMap PerThreadFunctionStack;9798/// Usefull object for getting human readable Symbol Names.99FuncIdConversionHelper FuncIdHelper;100bool DeduceSiblingCalls = false;101TimestampT CurrentMaxTSC = 0;102103/// A private function to help implement the statistic generation functions;104template <typename U>105void getStats(U begin, U end, GraphRenderer::TimeStat &S);106void updateMaxStats(const TimeStat &S, TimeStat &M);107108/// Calculates latency statistics for each edge and stores the data in the109/// Graph110void calculateEdgeStatistics();111112/// Calculates latency statistics for each vertex and stores the data in the113/// Graph114void calculateVertexStatistics();115116/// Normalises latency statistics for each edge and vertex by CycleFrequency;117void normalizeStatistics(double CycleFrequency);118119/// An object to color gradients120ColorHelper CHelper;121122public:123/// Takes in a reference to a FuncIdHelper in order to have ready access to124/// Symbol names.125explicit GraphRenderer(const FuncIdConversionHelper &FuncIdHelper, bool DSC)126: FuncIdHelper(FuncIdHelper), DeduceSiblingCalls(DSC),127CHelper(ColorHelper::SequentialScheme::OrRd) {128G[0] = {};129}130131/// Process an Xray record and expand the graph.132///133/// This Function will return true on success, or false if records are not134/// presented in per-thread call-tree DFS order. (That is for each thread the135/// Records should be in order runtime on an ideal system.)136///137/// FIXME: Make this more robust against small irregularities.138Error accountRecord(const XRayRecord &Record);139140const PerThreadFunctionStackMap &getPerThreadFunctionStack() const {141return PerThreadFunctionStack;142}143144class Factory {145public:146bool KeepGoing;147bool DeduceSiblingCalls;148std::string InstrMap;149::llvm::xray::Trace Trace;150Expected<GraphRenderer> getGraphRenderer();151};152153/// Output the Embedded graph in DOT format on \p OS, labeling the edges by154/// \p T155void exportGraphAsDOT(raw_ostream &OS, StatType EdgeLabel = StatType::NONE,156StatType EdgeColor = StatType::NONE,157StatType VertexLabel = StatType::NONE,158StatType VertexColor = StatType::NONE);159160/// Get a reference to the internal graph.161const GraphT &getGraph() { return G; }162};163164/// Vector Sum of TimeStats165inline GraphRenderer::TimeStat operator+(const GraphRenderer::TimeStat &A,166const GraphRenderer::TimeStat &B) {167return {A.Count + B.Count, A.Min + B.Min, A.Median + B.Median,168A.Pct90 + B.Pct90, A.Pct99 + B.Pct99, A.Max + B.Max,169A.Sum + B.Sum};170}171172/// Vector Difference of Timestats173inline GraphRenderer::TimeStat operator-(const GraphRenderer::TimeStat &A,174const GraphRenderer::TimeStat &B) {175176return {A.Count - B.Count, A.Min - B.Min, A.Median - B.Median,177A.Pct90 - B.Pct90, A.Pct99 - B.Pct99, A.Max - B.Max,178A.Sum - B.Sum};179}180181/// Scalar Diference of TimeStat and double182inline GraphRenderer::TimeStat operator/(const GraphRenderer::TimeStat &A,183double B) {184185return {static_cast<int64_t>(A.Count / B),186A.Min / B,187A.Median / B,188A.Pct90 / B,189A.Pct99 / B,190A.Max / B,191A.Sum / B};192}193194/// Scalar product of TimeStat and Double195inline GraphRenderer::TimeStat operator*(const GraphRenderer::TimeStat &A,196double B) {197return {static_cast<int64_t>(A.Count * B),198A.Min * B,199A.Median * B,200A.Pct90 * B,201A.Pct99 * B,202A.Max * B,203A.Sum * B};204}205206/// Scalar product of double TimeStat207inline GraphRenderer::TimeStat operator*(double A,208const GraphRenderer::TimeStat &B) {209return B * A;210}211212/// Hadamard Product of TimeStats213inline GraphRenderer::TimeStat operator*(const GraphRenderer::TimeStat &A,214const GraphRenderer::TimeStat &B) {215return {A.Count * B.Count, A.Min * B.Min, A.Median * B.Median,216A.Pct90 * B.Pct90, A.Pct99 * B.Pct99, A.Max * B.Max,217A.Sum * B.Sum};218}219220/// Hadamard Division of TimeStats221inline GraphRenderer::TimeStat operator/(const GraphRenderer::TimeStat &A,222const GraphRenderer::TimeStat &B) {223return {A.Count / B.Count, A.Min / B.Min, A.Median / B.Median,224A.Pct90 / B.Pct90, A.Pct99 / B.Pct99, A.Max / B.Max,225A.Sum / B.Sum};226}227} // namespace xray228} // namespace llvm229230#endif // XRAY_GRAPH_H231232233