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