blob: 1c7a3c0ef454b7e8dc8834b39632a49fa9b6d570 [file] [log] [blame]
David Blaikie87299ad2017-01-16 20:36:26 +00001//===-- xray-graph.h - XRay Function Call Graph Renderer --------*- C++ -*-===//
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// Generate a DOT file to represent the function call graph encountered in
11// the trace.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef XRAY_GRAPH_H
16#define XRAY_GRAPH_H
17
Dean Michael Berrisd09bf192017-01-25 07:14:43 +000018#include <string>
David Blaikie87299ad2017-01-16 20:36:26 +000019#include <vector>
20
21#include "func-id-helper.h"
Dean Michael Berrisf0cb13d2017-02-25 00:26:42 +000022#include "xray-color-helper.h"
David Blaikie87299ad2017-01-16 20:36:26 +000023#include "llvm/ADT/DenseMap.h"
24#include "llvm/ADT/SmallVector.h"
Dean Michael Berrisd09bf192017-01-25 07:14:43 +000025#include "llvm/Support/Errc.h"
Pavel Labath9778921a2017-01-17 09:39:31 +000026#include "llvm/Support/Program.h"
Dean Michael Berrisd09bf192017-01-25 07:14:43 +000027#include "llvm/Support/raw_ostream.h"
Dean Michael Berris6c97b3a2017-02-10 06:36:08 +000028#include "llvm/XRay/Graph.h"
David Blaikie87299ad2017-01-16 20:36:26 +000029#include "llvm/XRay/Trace.h"
30#include "llvm/XRay/XRayRecord.h"
31
32namespace llvm {
33namespace xray {
34
35/// A class encapsulating the logic related to analyzing XRay traces, producting
36/// Graphs from them and then exporting those graphs for review.
37class GraphRenderer {
38public:
Dean Michael Berrisd09bf192017-01-25 07:14:43 +000039 /// An enum for enumerating the various statistics gathered on latencies
40 enum class StatType { NONE, COUNT, MIN, MED, PCT90, PCT99, MAX, SUM };
41
David Blaikie87299ad2017-01-16 20:36:26 +000042 /// An inner struct for common timing statistics information
43 struct TimeStat {
Dean Michael Berrisd09bf192017-01-25 07:14:43 +000044 uint64_t Count = 0;
45 double Min = 0;
46 double Median = 0;
47 double Pct90 = 0;
48 double Pct99 = 0;
49 double Max = 0;
50 double Sum = 0;
51 std::string getAsString(StatType T) const;
52 double compare(StatType T, const TimeStat &Other) const;
David Blaikie87299ad2017-01-16 20:36:26 +000053 };
Dean Michael Berris6c97b3a2017-02-10 06:36:08 +000054 typedef uint64_t TimestampT;
David Blaikie87299ad2017-01-16 20:36:26 +000055
56 /// An inner struct for storing edge attributes for our graph. Here the
57 /// attributes are mainly function call statistics.
58 ///
59 /// FIXME: expand to contain more information eg call latencies.
Dean Michael Berris6c97b3a2017-02-10 06:36:08 +000060 struct CallStats {
David Blaikie87299ad2017-01-16 20:36:26 +000061 TimeStat S;
Dean Michael Berris6c97b3a2017-02-10 06:36:08 +000062 std::vector<TimestampT> Timings;
David Blaikie87299ad2017-01-16 20:36:26 +000063 };
64
65 /// An Inner Struct for storing vertex attributes, at the moment just
66 /// SymbolNames, however in future we could store bulk function statistics.
67 ///
68 /// FIXME: Store more attributes based on instrumentation map.
Dean Michael Berris6c97b3a2017-02-10 06:36:08 +000069 struct FunctionStats {
David Blaikie87299ad2017-01-16 20:36:26 +000070 std::string SymbolName;
71 TimeStat S;
72 };
73
Dean Michael Berrisd09bf192017-01-25 07:14:43 +000074 struct FunctionAttr {
75 int32_t FuncId;
76 uint64_t TSC;
77 };
78
79 typedef SmallVector<FunctionAttr, 4> FunctionStack;
80
81 typedef DenseMap<llvm::sys::ProcessInfo::ProcessId, FunctionStack>
82 PerThreadFunctionStackMap;
83
Dean Michael Berris6c97b3a2017-02-10 06:36:08 +000084 class GraphT : public Graph<FunctionStats, CallStats, int32_t> {
85 public:
86 TimeStat GraphEdgeMax = {};
87 TimeStat GraphVertexMax = {};
88 };
David Blaikie87299ad2017-01-16 20:36:26 +000089
Dean Michael Berris6c97b3a2017-02-10 06:36:08 +000090 GraphT G;
91 typedef typename decltype(G)::VertexIdentifier VertexIdentifier;
92 typedef typename decltype(G)::EdgeIdentifier EdgeIdentifier;
David Blaikie87299ad2017-01-16 20:36:26 +000093
94 /// Use a Map to store the Function stack for each thread whilst building the
95 /// graph.
96 ///
97 /// FIXME: Perhaps we can Build this into LatencyAccountant? or vise versa?
Dean Michael Berrisd09bf192017-01-25 07:14:43 +000098 PerThreadFunctionStackMap PerThreadFunctionStack;
David Blaikie87299ad2017-01-16 20:36:26 +000099
100 /// Usefull object for getting human readable Symbol Names.
Dean Michael Berrisf0cb13d2017-02-25 00:26:42 +0000101 const FuncIdConversionHelper &FuncIdHelper;
David Blaikie87299ad2017-01-16 20:36:26 +0000102 bool DeduceSiblingCalls = false;
Dean Michael Berris6c97b3a2017-02-10 06:36:08 +0000103 TimestampT CurrentMaxTSC = 0;
David Blaikie87299ad2017-01-16 20:36:26 +0000104
105 /// A private function to help implement the statistic generation functions;
106 template <typename U>
107 void getStats(U begin, U end, GraphRenderer::TimeStat &S);
Dean Michael Berrisd09bf192017-01-25 07:14:43 +0000108 void updateMaxStats(const TimeStat &S, TimeStat &M);
David Blaikie87299ad2017-01-16 20:36:26 +0000109
110 /// Calculates latency statistics for each edge and stores the data in the
111 /// Graph
112 void calculateEdgeStatistics();
113
114 /// Calculates latency statistics for each vertex and stores the data in the
115 /// Graph
116 void calculateVertexStatistics();
117
118 /// Normalises latency statistics for each edge and vertex by CycleFrequency;
Dean Michael Berrisd09bf192017-01-25 07:14:43 +0000119 void normalizeStatistics(double CycleFrequency);
David Blaikie87299ad2017-01-16 20:36:26 +0000120
Dean Michael Berrisf0cb13d2017-02-25 00:26:42 +0000121 /// An object to color gradients
122 ColorHelper CHelper;
123
David Blaikie87299ad2017-01-16 20:36:26 +0000124public:
125 /// Takes in a reference to a FuncIdHelper in order to have ready access to
126 /// Symbol names.
Dean Michael Berrisf0cb13d2017-02-25 00:26:42 +0000127 explicit GraphRenderer(const FuncIdConversionHelper &FuncIdHelper, bool DSC)
128 : FuncIdHelper(FuncIdHelper), DeduceSiblingCalls(DSC),
129 CHelper(ColorHelper::SequentialScheme::OrRd) {
Dean Michael Berris6c97b3a2017-02-10 06:36:08 +0000130 G[0] = {};
131 }
David Blaikie87299ad2017-01-16 20:36:26 +0000132
133 /// Process an Xray record and expand the graph.
134 ///
135 /// This Function will return true on success, or false if records are not
136 /// presented in per-thread call-tree DFS order. (That is for each thread the
137 /// Records should be in order runtime on an ideal system.)
138 ///
139 /// FIXME: Make this more robust against small irregularities.
Dean Michael Berrisd09bf192017-01-25 07:14:43 +0000140 Error accountRecord(const XRayRecord &Record);
David Blaikie87299ad2017-01-16 20:36:26 +0000141
Dean Michael Berris6c97b3a2017-02-10 06:36:08 +0000142 const PerThreadFunctionStackMap &getPerThreadFunctionStack() const {
Dean Michael Berrisd09bf192017-01-25 07:14:43 +0000143 return PerThreadFunctionStack;
144 }
David Blaikie87299ad2017-01-16 20:36:26 +0000145
146 /// Output the Embedded graph in DOT format on \p OS, labeling the edges by
147 /// \p T
148 void exportGraphAsDOT(raw_ostream &OS, const XRayFileHeader &H,
Dean Michael Berrisd09bf192017-01-25 07:14:43 +0000149 StatType EdgeLabel = StatType::NONE,
150 StatType EdgeColor = StatType::NONE,
151 StatType VertexLabel = StatType::NONE,
152 StatType VertexColor = StatType::NONE);
Dean Michael Berris6c97b3a2017-02-10 06:36:08 +0000153
154 /// Get a reference to the internal graph.
155 const GraphT &getGraph() {
156 calculateEdgeStatistics();
157 calculateVertexStatistics();
158 return G;
159 }
David Blaikie87299ad2017-01-16 20:36:26 +0000160};
161}
162}
163
164#endif // XRAY_GRAPH_H