1 //===- xray-account.h - XRay Function Call Accounting ---------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file defines the interface for performing some basic function call
10 // accounting from an XRay trace.
12 //===----------------------------------------------------------------------===//
13 #ifndef LLVM_TOOLS_LLVM_XRAY_XRAY_ACCOUNT_H
14 #define LLVM_TOOLS_LLVM_XRAY_XRAY_ACCOUNT_H
18 #include "func-id-helper.h"
19 #include "llvm/ADT/Bitfields.h"
20 #include "llvm/Support/Program.h"
21 #include "llvm/Support/raw_ostream.h"
22 #include "llvm/XRay/XRayRecord.h"
27 class LatencyAccountant
{
29 typedef llvm::DenseMap
<int32_t, llvm::SmallVector
<uint64_t, 0>>
31 typedef llvm::DenseMap
<uint32_t, std::pair
<uint64_t, uint64_t>>
32 PerThreadMinMaxTSCMap
;
33 typedef llvm::DenseMap
<uint8_t, std::pair
<uint64_t, uint64_t>>
35 struct FunctionStack
{
36 llvm::SmallVector
<std::pair
<int32_t, uint64_t>, 32> Stack
;
37 class RecursionStatus
{
39 using Depth
= Bitfield::Element
<int32_t, 0, 31>; // Low 31 bits.
40 using IsRecursive
= Bitfield::Element
<bool, 31, 1>; // Sign bit.
42 RecursionStatus
&operator++();
43 RecursionStatus
&operator--();
44 bool isRecursive() const;
46 std::optional
<llvm::DenseMap
<int32_t, RecursionStatus
>> RecursionDepth
;
48 typedef llvm::DenseMap
<uint32_t, FunctionStack
> PerThreadFunctionStackMap
;
51 PerThreadFunctionStackMap PerThreadFunctionStack
;
52 FunctionLatencyMap FunctionLatencies
;
53 PerThreadMinMaxTSCMap PerThreadMinMaxTSC
;
54 PerCPUMinMaxTSCMap PerCPUMinMaxTSC
;
55 FuncIdConversionHelper
&FuncIdHelper
;
57 bool RecursiveCallsOnly
= false;
58 bool DeduceSiblingCalls
= false;
59 uint64_t CurrentMaxTSC
= 0;
61 void recordLatency(int32_t FuncId
, uint64_t Latency
) {
62 FunctionLatencies
[FuncId
].push_back(Latency
);
66 explicit LatencyAccountant(FuncIdConversionHelper
&FuncIdHelper
,
67 bool RecursiveCallsOnly
, bool DeduceSiblingCalls
)
68 : FuncIdHelper(FuncIdHelper
), RecursiveCallsOnly(RecursiveCallsOnly
),
69 DeduceSiblingCalls(DeduceSiblingCalls
) {}
71 const FunctionLatencyMap
&getFunctionLatencies() const {
72 return FunctionLatencies
;
75 const PerThreadMinMaxTSCMap
&getPerThreadMinMaxTSC() const {
76 return PerThreadMinMaxTSC
;
79 const PerCPUMinMaxTSCMap
&getPerCPUMinMaxTSC() const {
80 return PerCPUMinMaxTSC
;
83 /// Returns false in case we fail to account the provided record. This happens
84 /// in the following cases:
86 /// - An exit record does not match any entry records for the same function.
87 /// If we've been set to deduce sibling calls, we try walking up the stack
88 /// and recording times for the higher level functions.
89 /// - A record has a TSC that's before the latest TSC that has been
90 /// recorded. We still record the TSC for the min-max.
92 bool accountRecord(const XRayRecord
&Record
);
94 const PerThreadFunctionStackMap
&getPerThreadFunctionStack() const {
95 return PerThreadFunctionStack
;
101 void exportStatsAsText(raw_ostream
&OS
, const XRayFileHeader
&Header
) const;
102 void exportStatsAsCSV(raw_ostream
&OS
, const XRayFileHeader
&Header
) const;
105 // Internal helper to implement common parts of the exportStatsAs...
107 template <class F
> void exportStats(const XRayFileHeader
&Header
, F fn
) const;
113 #endif // LLVM_TOOLS_LLVM_XRAY_XRAY_ACCOUNT_H