blob: fd8ac17f902aa43faf6acf4cbf4d3641300754ec [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"
22#include "llvm/ADT/DenseMap.h"
23#include "llvm/ADT/SmallVector.h"
Dean Michael Berrisd09bf192017-01-25 07:14:43 +000024#include "llvm/Support/Errc.h"
Pavel Labath9778921a2017-01-17 09:39:31 +000025#include "llvm/Support/Program.h"
Dean Michael Berrisd09bf192017-01-25 07:14:43 +000026#include "llvm/Support/raw_ostream.h"
Dean Michael Berris6c97b3a2017-02-10 06:36:08 +000027#include "llvm/XRay/Graph.h"
David Blaikie87299ad2017-01-16 20:36:26 +000028#include "llvm/XRay/Trace.h"
29#include "llvm/XRay/XRayRecord.h"
30
31namespace llvm {
32namespace xray {
33
34/// A class encapsulating the logic related to analyzing XRay traces, producting
35/// Graphs from them and then exporting those graphs for review.
36class GraphRenderer {
37public:
Dean Michael Berrisd09bf192017-01-25 07:14:43 +000038 /// An enum for enumerating the various statistics gathered on latencies
39 enum class StatType { NONE, COUNT, MIN, MED, PCT90, PCT99, MAX, SUM };
40
David Blaikie87299ad2017-01-16 20:36:26 +000041 /// An inner struct for common timing statistics information
42 struct TimeStat {
Dean Michael Berrisd09bf192017-01-25 07:14:43 +000043 uint64_t Count = 0;
44 double Min = 0;
45 double Median = 0;
46 double Pct90 = 0;
47 double Pct99 = 0;
48 double Max = 0;
49 double Sum = 0;
50 std::string getAsString(StatType T) const;
51 double compare(StatType T, const TimeStat &Other) const;
David Blaikie87299ad2017-01-16 20:36:26 +000052 };
Dean Michael Berris6c97b3a2017-02-10 06:36:08 +000053 typedef uint64_t TimestampT;
David Blaikie87299ad2017-01-16 20:36:26 +000054
55 /// An inner struct for storing edge attributes for our graph. Here the
56 /// attributes are mainly function call statistics.
57 ///
58 /// FIXME: expand to contain more information eg call latencies.
Dean Michael Berris6c97b3a2017-02-10 06:36:08 +000059 struct CallStats {
David Blaikie87299ad2017-01-16 20:36:26 +000060 TimeStat S;
Dean Michael Berris6c97b3a2017-02-10 06:36:08 +000061 std::vector<TimestampT> Timings;
David Blaikie87299ad2017-01-16 20:36:26 +000062 };
63
64 /// An Inner Struct for storing vertex attributes, at the moment just
65 /// SymbolNames, however in future we could store bulk function statistics.
66 ///
67 /// FIXME: Store more attributes based on instrumentation map.
Dean Michael Berris6c97b3a2017-02-10 06:36:08 +000068 struct FunctionStats {
David Blaikie87299ad2017-01-16 20:36:26 +000069 std::string SymbolName;
70 TimeStat S;
71 };
72
Dean Michael Berrisd09bf192017-01-25 07:14:43 +000073 struct FunctionAttr {
74 int32_t FuncId;
75 uint64_t TSC;
76 };
77
78 typedef SmallVector<FunctionAttr, 4> FunctionStack;
79
80 typedef DenseMap<llvm::sys::ProcessInfo::ProcessId, FunctionStack>
81 PerThreadFunctionStackMap;
82
Dean Michael Berris6c97b3a2017-02-10 06:36:08 +000083 class GraphT : public Graph<FunctionStats, CallStats, int32_t> {
84 public:
85 TimeStat GraphEdgeMax = {};
86 TimeStat GraphVertexMax = {};
87 };
David Blaikie87299ad2017-01-16 20:36:26 +000088
Dean Michael Berris6c97b3a2017-02-10 06:36:08 +000089 GraphT G;
90 typedef typename decltype(G)::VertexIdentifier VertexIdentifier;
91 typedef typename decltype(G)::EdgeIdentifier EdgeIdentifier;
David Blaikie87299ad2017-01-16 20:36:26 +000092
93 /// Use a Map to store the Function stack for each thread whilst building the
94 /// graph.
95 ///
96 /// FIXME: Perhaps we can Build this into LatencyAccountant? or vise versa?
Dean Michael Berrisd09bf192017-01-25 07:14:43 +000097 PerThreadFunctionStackMap PerThreadFunctionStack;
David Blaikie87299ad2017-01-16 20:36:26 +000098
99 /// Usefull object for getting human readable Symbol Names.
100 FuncIdConversionHelper &FuncIdHelper;
101 bool DeduceSiblingCalls = false;
Dean Michael Berris6c97b3a2017-02-10 06:36:08 +0000102 TimestampT CurrentMaxTSC = 0;
David Blaikie87299ad2017-01-16 20:36:26 +0000103
104 /// A private function to help implement the statistic generation functions;
105 template <typename U>
106 void getStats(U begin, U end, GraphRenderer::TimeStat &S);
Dean Michael Berrisd09bf192017-01-25 07:14:43 +0000107 void updateMaxStats(const TimeStat &S, TimeStat &M);
David Blaikie87299ad2017-01-16 20:36:26 +0000108
109 /// Calculates latency statistics for each edge and stores the data in the
110 /// Graph
111 void calculateEdgeStatistics();
112
113 /// Calculates latency statistics for each vertex and stores the data in the
114 /// Graph
115 void calculateVertexStatistics();
116
117 /// Normalises latency statistics for each edge and vertex by CycleFrequency;
Dean Michael Berrisd09bf192017-01-25 07:14:43 +0000118 void normalizeStatistics(double CycleFrequency);
David Blaikie87299ad2017-01-16 20:36:26 +0000119
120public:
121 /// Takes in a reference to a FuncIdHelper in order to have ready access to
122 /// Symbol names.
123 explicit GraphRenderer(FuncIdConversionHelper &FuncIdHelper, bool DSC)
Dean Michael Berris6c97b3a2017-02-10 06:36:08 +0000124 : FuncIdHelper(FuncIdHelper), DeduceSiblingCalls(DSC) {
125 G[0] = {};
126 }
David Blaikie87299ad2017-01-16 20:36:26 +0000127
128 /// Process an Xray record and expand the graph.
129 ///
130 /// This Function will return true on success, or false if records are not
131 /// presented in per-thread call-tree DFS order. (That is for each thread the
132 /// Records should be in order runtime on an ideal system.)
133 ///
134 /// FIXME: Make this more robust against small irregularities.
Dean Michael Berrisd09bf192017-01-25 07:14:43 +0000135 Error accountRecord(const XRayRecord &Record);
David Blaikie87299ad2017-01-16 20:36:26 +0000136
Dean Michael Berris6c97b3a2017-02-10 06:36:08 +0000137 const PerThreadFunctionStackMap &getPerThreadFunctionStack() const {
Dean Michael Berrisd09bf192017-01-25 07:14:43 +0000138 return PerThreadFunctionStack;
139 }
David Blaikie87299ad2017-01-16 20:36:26 +0000140
141 /// Output the Embedded graph in DOT format on \p OS, labeling the edges by
142 /// \p T
143 void exportGraphAsDOT(raw_ostream &OS, const XRayFileHeader &H,
Dean Michael Berrisd09bf192017-01-25 07:14:43 +0000144 StatType EdgeLabel = StatType::NONE,
145 StatType EdgeColor = StatType::NONE,
146 StatType VertexLabel = StatType::NONE,
147 StatType VertexColor = StatType::NONE);
Dean Michael Berris6c97b3a2017-02-10 06:36:08 +0000148
149 /// Get a reference to the internal graph.
150 const GraphT &getGraph() {
151 calculateEdgeStatistics();
152 calculateVertexStatistics();
153 return G;
154 }
David Blaikie87299ad2017-01-16 20:36:26 +0000155};
156}
157}
158
159#endif // XRAY_GRAPH_H