blob: fc7f8bb470f24319848c31eb703661eafc8d2062 [file] [log] [blame]
David Blaikie061ca192017-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 Berris420c0702017-01-25 07:14:43 +000018#include <string>
David Blaikie061ca192017-01-16 20:36:26 +000019#include <vector>
20
21#include "func-id-helper.h"
Dean Michael Berrisde5a65f2017-02-25 00:26:42 +000022#include "xray-color-helper.h"
David Blaikie061ca192017-01-16 20:36:26 +000023#include "llvm/ADT/DenseMap.h"
24#include "llvm/ADT/SmallVector.h"
Dean Michael Berris420c0702017-01-25 07:14:43 +000025#include "llvm/Support/Errc.h"
Pavel Labathc52f4a42017-01-17 09:39:31 +000026#include "llvm/Support/Program.h"
Dean Michael Berris420c0702017-01-25 07:14:43 +000027#include "llvm/Support/raw_ostream.h"
Dean Michael Berris4dc48bf2017-02-10 06:36:08 +000028#include "llvm/XRay/Graph.h"
David Blaikie061ca192017-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 Berris420c0702017-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 Blaikie061ca192017-01-16 20:36:26 +000042 /// An inner struct for common timing statistics information
43 struct TimeStat {
Dean Michael Berrisae0fbfb2017-04-24 05:54:33 +000044 int64_t Count;
45 double Min;
46 double Median;
47 double Pct90;
48 double Pct99;
49 double Max;
50 double Sum;
51
52 std::string getString(StatType T) const;
53 double getDouble(StatType T) const;
David Blaikie061ca192017-01-16 20:36:26 +000054 };
Dean Michael Berrisae0fbfb2017-04-24 05:54:33 +000055 using TimestampT = uint64_t;
David Blaikie061ca192017-01-16 20:36:26 +000056
57 /// An inner struct for storing edge attributes for our graph. Here the
58 /// attributes are mainly function call statistics.
59 ///
60 /// FIXME: expand to contain more information eg call latencies.
Dean Michael Berris4dc48bf2017-02-10 06:36:08 +000061 struct CallStats {
David Blaikie061ca192017-01-16 20:36:26 +000062 TimeStat S;
Dean Michael Berris4dc48bf2017-02-10 06:36:08 +000063 std::vector<TimestampT> Timings;
David Blaikie061ca192017-01-16 20:36:26 +000064 };
65
66 /// An Inner Struct for storing vertex attributes, at the moment just
67 /// SymbolNames, however in future we could store bulk function statistics.
68 ///
69 /// FIXME: Store more attributes based on instrumentation map.
Dean Michael Berris4dc48bf2017-02-10 06:36:08 +000070 struct FunctionStats {
David Blaikie061ca192017-01-16 20:36:26 +000071 std::string SymbolName;
Dean Michael Berrisae0fbfb2017-04-24 05:54:33 +000072 TimeStat S = {};
David Blaikie061ca192017-01-16 20:36:26 +000073 };
74
Dean Michael Berris420c0702017-01-25 07:14:43 +000075 struct FunctionAttr {
76 int32_t FuncId;
77 uint64_t TSC;
78 };
79
Dean Michael Berrisae0fbfb2017-04-24 05:54:33 +000080 using FunctionStack = SmallVector<FunctionAttr, 4>;
Dean Michael Berris420c0702017-01-25 07:14:43 +000081
Dean Michael Berrisae0fbfb2017-04-24 05:54:33 +000082 using PerThreadFunctionStackMap =
Zachary Turner370ce5a2018-06-08 15:16:25 +000083 DenseMap<llvm::sys::procid_t, FunctionStack>;
Dean Michael Berris420c0702017-01-25 07:14:43 +000084
Dean Michael Berris4dc48bf2017-02-10 06:36:08 +000085 class GraphT : public Graph<FunctionStats, CallStats, int32_t> {
86 public:
87 TimeStat GraphEdgeMax = {};
88 TimeStat GraphVertexMax = {};
89 };
David Blaikie061ca192017-01-16 20:36:26 +000090
Dean Michael Berris4dc48bf2017-02-10 06:36:08 +000091 GraphT G;
Dean Michael Berrisae0fbfb2017-04-24 05:54:33 +000092 using VertexIdentifier = typename decltype(G)::VertexIdentifier;
93 using EdgeIdentifier = decltype(G)::EdgeIdentifier;
David Blaikie061ca192017-01-16 20:36:26 +000094
95 /// Use a Map to store the Function stack for each thread whilst building the
96 /// graph.
97 ///
98 /// FIXME: Perhaps we can Build this into LatencyAccountant? or vise versa?
Dean Michael Berris420c0702017-01-25 07:14:43 +000099 PerThreadFunctionStackMap PerThreadFunctionStack;
David Blaikie061ca192017-01-16 20:36:26 +0000100
101 /// Usefull object for getting human readable Symbol Names.
Dean Michael Berrisae0fbfb2017-04-24 05:54:33 +0000102 FuncIdConversionHelper FuncIdHelper;
David Blaikie061ca192017-01-16 20:36:26 +0000103 bool DeduceSiblingCalls = false;
Dean Michael Berris4dc48bf2017-02-10 06:36:08 +0000104 TimestampT CurrentMaxTSC = 0;
David Blaikie061ca192017-01-16 20:36:26 +0000105
106 /// A private function to help implement the statistic generation functions;
107 template <typename U>
108 void getStats(U begin, U end, GraphRenderer::TimeStat &S);
Dean Michael Berris420c0702017-01-25 07:14:43 +0000109 void updateMaxStats(const TimeStat &S, TimeStat &M);
David Blaikie061ca192017-01-16 20:36:26 +0000110
111 /// Calculates latency statistics for each edge and stores the data in the
112 /// Graph
113 void calculateEdgeStatistics();
114
115 /// Calculates latency statistics for each vertex and stores the data in the
116 /// Graph
117 void calculateVertexStatistics();
118
119 /// Normalises latency statistics for each edge and vertex by CycleFrequency;
Dean Michael Berris420c0702017-01-25 07:14:43 +0000120 void normalizeStatistics(double CycleFrequency);
David Blaikie061ca192017-01-16 20:36:26 +0000121
Dean Michael Berrisde5a65f2017-02-25 00:26:42 +0000122 /// An object to color gradients
123 ColorHelper CHelper;
124
David Blaikie061ca192017-01-16 20:36:26 +0000125public:
126 /// Takes in a reference to a FuncIdHelper in order to have ready access to
127 /// Symbol names.
Dean Michael Berrisde5a65f2017-02-25 00:26:42 +0000128 explicit GraphRenderer(const FuncIdConversionHelper &FuncIdHelper, bool DSC)
129 : FuncIdHelper(FuncIdHelper), DeduceSiblingCalls(DSC),
130 CHelper(ColorHelper::SequentialScheme::OrRd) {
Dean Michael Berris4dc48bf2017-02-10 06:36:08 +0000131 G[0] = {};
132 }
David Blaikie061ca192017-01-16 20:36:26 +0000133
134 /// Process an Xray record and expand the graph.
135 ///
136 /// This Function will return true on success, or false if records are not
137 /// presented in per-thread call-tree DFS order. (That is for each thread the
138 /// Records should be in order runtime on an ideal system.)
139 ///
140 /// FIXME: Make this more robust against small irregularities.
Dean Michael Berris420c0702017-01-25 07:14:43 +0000141 Error accountRecord(const XRayRecord &Record);
David Blaikie061ca192017-01-16 20:36:26 +0000142
Dean Michael Berris4dc48bf2017-02-10 06:36:08 +0000143 const PerThreadFunctionStackMap &getPerThreadFunctionStack() const {
Dean Michael Berris420c0702017-01-25 07:14:43 +0000144 return PerThreadFunctionStack;
145 }
David Blaikie061ca192017-01-16 20:36:26 +0000146
Dean Michael Berrisae0fbfb2017-04-24 05:54:33 +0000147 class Factory {
148 public:
149 bool KeepGoing;
150 bool DeduceSiblingCalls;
151 std::string InstrMap;
Dean Michael Berris0d479b02017-04-24 06:15:53 +0000152 ::llvm::xray::Trace Trace;
Dean Michael Berrisae0fbfb2017-04-24 05:54:33 +0000153 Expected<GraphRenderer> getGraphRenderer();
154 };
155
David Blaikie061ca192017-01-16 20:36:26 +0000156 /// Output the Embedded graph in DOT format on \p OS, labeling the edges by
157 /// \p T
Dean Michael Berrisae0fbfb2017-04-24 05:54:33 +0000158 void exportGraphAsDOT(raw_ostream &OS, StatType EdgeLabel = StatType::NONE,
Dean Michael Berris420c0702017-01-25 07:14:43 +0000159 StatType EdgeColor = StatType::NONE,
160 StatType VertexLabel = StatType::NONE,
161 StatType VertexColor = StatType::NONE);
Dean Michael Berris4dc48bf2017-02-10 06:36:08 +0000162
163 /// Get a reference to the internal graph.
Dean Michael Berrisae0fbfb2017-04-24 05:54:33 +0000164 const GraphT &getGraph() { return G; }
David Blaikie061ca192017-01-16 20:36:26 +0000165};
Dean Michael Berrisae0fbfb2017-04-24 05:54:33 +0000166
167/// Vector Sum of TimeStats
168inline GraphRenderer::TimeStat operator+(const GraphRenderer::TimeStat &A,
169 const GraphRenderer::TimeStat &B) {
170 return {A.Count + B.Count, A.Min + B.Min, A.Median + B.Median,
171 A.Pct90 + B.Pct90, A.Pct99 + B.Pct99, A.Max + B.Max,
172 A.Sum + B.Sum};
David Blaikie061ca192017-01-16 20:36:26 +0000173}
Dean Michael Berrisae0fbfb2017-04-24 05:54:33 +0000174
175/// Vector Difference of Timestats
176inline GraphRenderer::TimeStat operator-(const GraphRenderer::TimeStat &A,
177 const GraphRenderer::TimeStat &B) {
178
179 return {A.Count - B.Count, A.Min - B.Min, A.Median - B.Median,
180 A.Pct90 - B.Pct90, A.Pct99 - B.Pct99, A.Max - B.Max,
181 A.Sum - B.Sum};
David Blaikie061ca192017-01-16 20:36:26 +0000182}
183
Dean Michael Berrisae0fbfb2017-04-24 05:54:33 +0000184/// Scalar Diference of TimeStat and double
185inline GraphRenderer::TimeStat operator/(const GraphRenderer::TimeStat &A,
186 double B) {
187
188 return {static_cast<int64_t>(A.Count / B),
189 A.Min / B,
190 A.Median / B,
191 A.Pct90 / B,
192 A.Pct99 / B,
193 A.Max / B,
194 A.Sum / B};
195}
196
197/// Scalar product of TimeStat and Double
198inline GraphRenderer::TimeStat operator*(const GraphRenderer::TimeStat &A,
199 double B) {
200 return {static_cast<int64_t>(A.Count * B),
201 A.Min * B,
202 A.Median * B,
203 A.Pct90 * B,
204 A.Pct99 * B,
205 A.Max * B,
206 A.Sum * B};
207}
208
209/// Scalar product of double TimeStat
210inline GraphRenderer::TimeStat operator*(double A,
211 const GraphRenderer::TimeStat &B) {
212 return B * A;
213}
214
215/// Hadamard Product of TimeStats
216inline GraphRenderer::TimeStat operator*(const GraphRenderer::TimeStat &A,
217 const GraphRenderer::TimeStat &B) {
218 return {A.Count * B.Count, A.Min * B.Min, A.Median * B.Median,
219 A.Pct90 * B.Pct90, A.Pct99 * B.Pct99, A.Max * B.Max,
220 A.Sum * B.Sum};
221}
222
223/// Hadamard Division of TimeStats
224inline GraphRenderer::TimeStat operator/(const GraphRenderer::TimeStat &A,
225 const GraphRenderer::TimeStat &B) {
Dean Michael Berris8577a8c2017-04-26 01:35:23 +0000226 return {A.Count / B.Count, A.Min / B.Min, A.Median / B.Median,
227 A.Pct90 / B.Pct90, A.Pct99 / B.Pct99, A.Max / B.Max,
228 A.Sum / B.Sum};
Dean Michael Berrisae0fbfb2017-04-24 05:54:33 +0000229}
230} // namespace xray
231} // namespace llvm
232
David Blaikie061ca192017-01-16 20:36:26 +0000233#endif // XRAY_GRAPH_H