xref: /freebsd/contrib/llvm-project/llvm/tools/llvm-xray/xray-account.h (revision e8d8bef961a50d4dc22501cde4fb9fb0be1b2532)
10b57cec5SDimitry Andric //===- xray-account.h - XRay Function Call Accounting ---------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file defines the interface for performing some basic function call
100b57cec5SDimitry Andric // accounting from an XRay trace.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric #ifndef LLVM_TOOLS_LLVM_XRAY_XRAY_ACCOUNT_H
140b57cec5SDimitry Andric #define LLVM_TOOLS_LLVM_XRAY_XRAY_ACCOUNT_H
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric #include <map>
170b57cec5SDimitry Andric #include <utility>
180b57cec5SDimitry Andric #include <vector>
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric #include "func-id-helper.h"
21*e8d8bef9SDimitry Andric #include "llvm/ADT/Bitfields.h"
220b57cec5SDimitry Andric #include "llvm/Support/Program.h"
230b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
240b57cec5SDimitry Andric #include "llvm/XRay/XRayRecord.h"
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric namespace llvm {
270b57cec5SDimitry Andric namespace xray {
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric class LatencyAccountant {
300b57cec5SDimitry Andric public:
31*e8d8bef9SDimitry Andric   typedef llvm::DenseMap<int32_t, llvm::SmallVector<uint64_t, 0>>
32*e8d8bef9SDimitry Andric       FunctionLatencyMap;
33*e8d8bef9SDimitry Andric   typedef llvm::DenseMap<uint32_t, std::pair<uint64_t, uint64_t>>
340b57cec5SDimitry Andric       PerThreadMinMaxTSCMap;
35*e8d8bef9SDimitry Andric   typedef llvm::DenseMap<uint8_t, std::pair<uint64_t, uint64_t>>
36*e8d8bef9SDimitry Andric       PerCPUMinMaxTSCMap;
37*e8d8bef9SDimitry Andric   struct FunctionStack {
38*e8d8bef9SDimitry Andric     llvm::SmallVector<std::pair<int32_t, uint64_t>, 32> Stack;
39*e8d8bef9SDimitry Andric     class RecursionStatus {
40*e8d8bef9SDimitry Andric       uint32_t Storage = 0;
41*e8d8bef9SDimitry Andric       using Depth = Bitfield::Element<int32_t, 0, 31>;    // Low 31 bits.
42*e8d8bef9SDimitry Andric       using IsRecursive = Bitfield::Element<bool, 31, 1>; // Sign bit.
43*e8d8bef9SDimitry Andric     public:
44*e8d8bef9SDimitry Andric       RecursionStatus &operator++();
45*e8d8bef9SDimitry Andric       RecursionStatus &operator--();
46*e8d8bef9SDimitry Andric       bool isRecursive() const;
47*e8d8bef9SDimitry Andric     };
48*e8d8bef9SDimitry Andric     Optional<llvm::DenseMap<int32_t, RecursionStatus>> RecursionDepth;
49*e8d8bef9SDimitry Andric   };
50*e8d8bef9SDimitry Andric   typedef llvm::DenseMap<uint32_t, FunctionStack> PerThreadFunctionStackMap;
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric private:
530b57cec5SDimitry Andric   PerThreadFunctionStackMap PerThreadFunctionStack;
540b57cec5SDimitry Andric   FunctionLatencyMap FunctionLatencies;
550b57cec5SDimitry Andric   PerThreadMinMaxTSCMap PerThreadMinMaxTSC;
560b57cec5SDimitry Andric   PerCPUMinMaxTSCMap PerCPUMinMaxTSC;
570b57cec5SDimitry Andric   FuncIdConversionHelper &FuncIdHelper;
580b57cec5SDimitry Andric 
59*e8d8bef9SDimitry Andric   bool RecursiveCallsOnly = false;
600b57cec5SDimitry Andric   bool DeduceSiblingCalls = false;
610b57cec5SDimitry Andric   uint64_t CurrentMaxTSC = 0;
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric   void recordLatency(int32_t FuncId, uint64_t Latency) {
640b57cec5SDimitry Andric     FunctionLatencies[FuncId].push_back(Latency);
650b57cec5SDimitry Andric   }
660b57cec5SDimitry Andric 
670b57cec5SDimitry Andric public:
680b57cec5SDimitry Andric   explicit LatencyAccountant(FuncIdConversionHelper &FuncIdHelper,
69*e8d8bef9SDimitry Andric                              bool RecursiveCallsOnly, bool DeduceSiblingCalls)
70*e8d8bef9SDimitry Andric       : FuncIdHelper(FuncIdHelper), RecursiveCallsOnly(RecursiveCallsOnly),
71*e8d8bef9SDimitry Andric         DeduceSiblingCalls(DeduceSiblingCalls) {}
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric   const FunctionLatencyMap &getFunctionLatencies() const {
740b57cec5SDimitry Andric     return FunctionLatencies;
750b57cec5SDimitry Andric   }
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric   const PerThreadMinMaxTSCMap &getPerThreadMinMaxTSC() const {
780b57cec5SDimitry Andric     return PerThreadMinMaxTSC;
790b57cec5SDimitry Andric   }
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric   const PerCPUMinMaxTSCMap &getPerCPUMinMaxTSC() const {
820b57cec5SDimitry Andric     return PerCPUMinMaxTSC;
830b57cec5SDimitry Andric   }
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric   /// Returns false in case we fail to account the provided record. This happens
860b57cec5SDimitry Andric   /// in the following cases:
870b57cec5SDimitry Andric   ///
880b57cec5SDimitry Andric   ///   - An exit record does not match any entry records for the same function.
890b57cec5SDimitry Andric   ///     If we've been set to deduce sibling calls, we try walking up the stack
900b57cec5SDimitry Andric   ///     and recording times for the higher level functions.
910b57cec5SDimitry Andric   ///   - A record has a TSC that's before the latest TSC that has been
920b57cec5SDimitry Andric   ///     recorded. We still record the TSC for the min-max.
930b57cec5SDimitry Andric   ///
940b57cec5SDimitry Andric   bool accountRecord(const XRayRecord &Record);
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric   const PerThreadFunctionStackMap &getPerThreadFunctionStack() const {
970b57cec5SDimitry Andric     return PerThreadFunctionStack;
980b57cec5SDimitry Andric   }
990b57cec5SDimitry Andric 
1000b57cec5SDimitry Andric   // Output Functions
1010b57cec5SDimitry Andric   // ================
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric   void exportStatsAsText(raw_ostream &OS, const XRayFileHeader &Header) const;
1040b57cec5SDimitry Andric   void exportStatsAsCSV(raw_ostream &OS, const XRayFileHeader &Header) const;
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric private:
1070b57cec5SDimitry Andric   // Internal helper to implement common parts of the exportStatsAs...
1080b57cec5SDimitry Andric   // functions.
1090b57cec5SDimitry Andric   template <class F> void exportStats(const XRayFileHeader &Header, F fn) const;
1100b57cec5SDimitry Andric };
1110b57cec5SDimitry Andric 
1120b57cec5SDimitry Andric } // namespace xray
1130b57cec5SDimitry Andric } // namespace llvm
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric #endif // LLVM_TOOLS_LLVM_XRAY_XRAY_ACCOUNT_H
116