xray-graph.h revision 317017
1317017Sdim//===-- xray-graph.h - XRay Function Call Graph Renderer --------*- C++ -*-===// 2317017Sdim// 3317017Sdim// The LLVM Compiler Infrastructure 4317017Sdim// 5317017Sdim// This file is distributed under the University of Illinois Open Source 6317017Sdim// License. See LICENSE.TXT for details. 7317017Sdim// 8317017Sdim//===----------------------------------------------------------------------===// 9317017Sdim// 10317017Sdim// Generate a DOT file to represent the function call graph encountered in 11317017Sdim// the trace. 12317017Sdim// 13317017Sdim//===----------------------------------------------------------------------===// 14317017Sdim 15317017Sdim#ifndef XRAY_GRAPH_H 16317017Sdim#define XRAY_GRAPH_H 17317017Sdim 18317017Sdim#include <string> 19317017Sdim#include <vector> 20317017Sdim 21317017Sdim#include "func-id-helper.h" 22317017Sdim#include "xray-color-helper.h" 23317017Sdim#include "llvm/ADT/DenseMap.h" 24317017Sdim#include "llvm/ADT/SmallVector.h" 25317017Sdim#include "llvm/Support/Errc.h" 26317017Sdim#include "llvm/Support/Program.h" 27317017Sdim#include "llvm/Support/raw_ostream.h" 28317017Sdim#include "llvm/XRay/Graph.h" 29317017Sdim#include "llvm/XRay/Trace.h" 30317017Sdim#include "llvm/XRay/XRayRecord.h" 31317017Sdim 32317017Sdimnamespace llvm { 33317017Sdimnamespace xray { 34317017Sdim 35317017Sdim/// A class encapsulating the logic related to analyzing XRay traces, producting 36317017Sdim/// Graphs from them and then exporting those graphs for review. 37317017Sdimclass GraphRenderer { 38317017Sdimpublic: 39317017Sdim /// An enum for enumerating the various statistics gathered on latencies 40317017Sdim enum class StatType { NONE, COUNT, MIN, MED, PCT90, PCT99, MAX, SUM }; 41317017Sdim 42317017Sdim /// An inner struct for common timing statistics information 43317017Sdim struct TimeStat { 44317017Sdim uint64_t Count = 0; 45317017Sdim double Min = 0; 46317017Sdim double Median = 0; 47317017Sdim double Pct90 = 0; 48317017Sdim double Pct99 = 0; 49317017Sdim double Max = 0; 50317017Sdim double Sum = 0; 51317017Sdim std::string getAsString(StatType T) const; 52317017Sdim double compare(StatType T, const TimeStat &Other) const; 53317017Sdim }; 54317017Sdim typedef uint64_t TimestampT; 55317017Sdim 56317017Sdim /// An inner struct for storing edge attributes for our graph. Here the 57317017Sdim /// attributes are mainly function call statistics. 58317017Sdim /// 59317017Sdim /// FIXME: expand to contain more information eg call latencies. 60317017Sdim struct CallStats { 61317017Sdim TimeStat S; 62317017Sdim std::vector<TimestampT> Timings; 63317017Sdim }; 64317017Sdim 65317017Sdim /// An Inner Struct for storing vertex attributes, at the moment just 66317017Sdim /// SymbolNames, however in future we could store bulk function statistics. 67317017Sdim /// 68317017Sdim /// FIXME: Store more attributes based on instrumentation map. 69317017Sdim struct FunctionStats { 70317017Sdim std::string SymbolName; 71317017Sdim TimeStat S; 72317017Sdim }; 73317017Sdim 74317017Sdim struct FunctionAttr { 75317017Sdim int32_t FuncId; 76317017Sdim uint64_t TSC; 77317017Sdim }; 78317017Sdim 79317017Sdim typedef SmallVector<FunctionAttr, 4> FunctionStack; 80317017Sdim 81317017Sdim typedef DenseMap<llvm::sys::ProcessInfo::ProcessId, FunctionStack> 82317017Sdim PerThreadFunctionStackMap; 83317017Sdim 84317017Sdim class GraphT : public Graph<FunctionStats, CallStats, int32_t> { 85317017Sdim public: 86317017Sdim TimeStat GraphEdgeMax = {}; 87317017Sdim TimeStat GraphVertexMax = {}; 88317017Sdim }; 89317017Sdim 90317017Sdim GraphT G; 91317017Sdim typedef typename decltype(G)::VertexIdentifier VertexIdentifier; 92317017Sdim typedef typename decltype(G)::EdgeIdentifier EdgeIdentifier; 93317017Sdim 94317017Sdim /// Use a Map to store the Function stack for each thread whilst building the 95317017Sdim /// graph. 96317017Sdim /// 97317017Sdim /// FIXME: Perhaps we can Build this into LatencyAccountant? or vise versa? 98317017Sdim PerThreadFunctionStackMap PerThreadFunctionStack; 99317017Sdim 100317017Sdim /// Usefull object for getting human readable Symbol Names. 101317017Sdim const FuncIdConversionHelper &FuncIdHelper; 102317017Sdim bool DeduceSiblingCalls = false; 103317017Sdim TimestampT CurrentMaxTSC = 0; 104317017Sdim 105317017Sdim /// A private function to help implement the statistic generation functions; 106317017Sdim template <typename U> 107317017Sdim void getStats(U begin, U end, GraphRenderer::TimeStat &S); 108317017Sdim void updateMaxStats(const TimeStat &S, TimeStat &M); 109317017Sdim 110317017Sdim /// Calculates latency statistics for each edge and stores the data in the 111317017Sdim /// Graph 112317017Sdim void calculateEdgeStatistics(); 113317017Sdim 114317017Sdim /// Calculates latency statistics for each vertex and stores the data in the 115317017Sdim /// Graph 116317017Sdim void calculateVertexStatistics(); 117317017Sdim 118317017Sdim /// Normalises latency statistics for each edge and vertex by CycleFrequency; 119317017Sdim void normalizeStatistics(double CycleFrequency); 120317017Sdim 121317017Sdim /// An object to color gradients 122317017Sdim ColorHelper CHelper; 123317017Sdim 124317017Sdimpublic: 125317017Sdim /// Takes in a reference to a FuncIdHelper in order to have ready access to 126317017Sdim /// Symbol names. 127317017Sdim explicit GraphRenderer(const FuncIdConversionHelper &FuncIdHelper, bool DSC) 128317017Sdim : FuncIdHelper(FuncIdHelper), DeduceSiblingCalls(DSC), 129317017Sdim CHelper(ColorHelper::SequentialScheme::OrRd) { 130317017Sdim G[0] = {}; 131317017Sdim } 132317017Sdim 133317017Sdim /// Process an Xray record and expand the graph. 134317017Sdim /// 135317017Sdim /// This Function will return true on success, or false if records are not 136317017Sdim /// presented in per-thread call-tree DFS order. (That is for each thread the 137317017Sdim /// Records should be in order runtime on an ideal system.) 138317017Sdim /// 139317017Sdim /// FIXME: Make this more robust against small irregularities. 140317017Sdim Error accountRecord(const XRayRecord &Record); 141317017Sdim 142317017Sdim const PerThreadFunctionStackMap &getPerThreadFunctionStack() const { 143317017Sdim return PerThreadFunctionStack; 144317017Sdim } 145317017Sdim 146317017Sdim /// Output the Embedded graph in DOT format on \p OS, labeling the edges by 147317017Sdim /// \p T 148317017Sdim void exportGraphAsDOT(raw_ostream &OS, const XRayFileHeader &H, 149317017Sdim StatType EdgeLabel = StatType::NONE, 150317017Sdim StatType EdgeColor = StatType::NONE, 151317017Sdim StatType VertexLabel = StatType::NONE, 152317017Sdim StatType VertexColor = StatType::NONE); 153317017Sdim 154317017Sdim /// Get a reference to the internal graph. 155317017Sdim const GraphT &getGraph() { 156317017Sdim calculateEdgeStatistics(); 157317017Sdim calculateVertexStatistics(); 158317017Sdim return G; 159317017Sdim } 160317017Sdim}; 161317017Sdim} 162317017Sdim} 163317017Sdim 164317017Sdim#endif // XRAY_GRAPH_H 165