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 <utility> 170b57cec5SDimitry Andric 180b57cec5SDimitry Andric #include "func-id-helper.h" 19e8d8bef9SDimitry Andric #include "llvm/ADT/Bitfields.h" 200b57cec5SDimitry Andric #include "llvm/Support/Program.h" 210b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 220b57cec5SDimitry Andric #include "llvm/XRay/XRayRecord.h" 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric namespace llvm { 250b57cec5SDimitry Andric namespace xray { 260b57cec5SDimitry Andric 270b57cec5SDimitry Andric class LatencyAccountant { 280b57cec5SDimitry Andric public: 29e8d8bef9SDimitry Andric typedef llvm::DenseMap<int32_t, llvm::SmallVector<uint64_t, 0>> 30e8d8bef9SDimitry Andric FunctionLatencyMap; 31e8d8bef9SDimitry Andric typedef llvm::DenseMap<uint32_t, std::pair<uint64_t, uint64_t>> 320b57cec5SDimitry Andric PerThreadMinMaxTSCMap; 33e8d8bef9SDimitry Andric typedef llvm::DenseMap<uint8_t, std::pair<uint64_t, uint64_t>> 34e8d8bef9SDimitry Andric PerCPUMinMaxTSCMap; 35e8d8bef9SDimitry Andric struct FunctionStack { 36e8d8bef9SDimitry Andric llvm::SmallVector<std::pair<int32_t, uint64_t>, 32> Stack; 37e8d8bef9SDimitry Andric class RecursionStatus { 38e8d8bef9SDimitry Andric uint32_t Storage = 0; 39e8d8bef9SDimitry Andric using Depth = Bitfield::Element<int32_t, 0, 31>; // Low 31 bits. 40e8d8bef9SDimitry Andric using IsRecursive = Bitfield::Element<bool, 31, 1>; // Sign bit. 41e8d8bef9SDimitry Andric public: 42e8d8bef9SDimitry Andric RecursionStatus &operator++(); 43e8d8bef9SDimitry Andric RecursionStatus &operator--(); 44e8d8bef9SDimitry Andric bool isRecursive() const; 45e8d8bef9SDimitry Andric }; 46*bdd1243dSDimitry Andric std::optional<llvm::DenseMap<int32_t, RecursionStatus>> RecursionDepth; 47e8d8bef9SDimitry Andric }; 48e8d8bef9SDimitry Andric typedef llvm::DenseMap<uint32_t, FunctionStack> PerThreadFunctionStackMap; 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric private: 510b57cec5SDimitry Andric PerThreadFunctionStackMap PerThreadFunctionStack; 520b57cec5SDimitry Andric FunctionLatencyMap FunctionLatencies; 530b57cec5SDimitry Andric PerThreadMinMaxTSCMap PerThreadMinMaxTSC; 540b57cec5SDimitry Andric PerCPUMinMaxTSCMap PerCPUMinMaxTSC; 550b57cec5SDimitry Andric FuncIdConversionHelper &FuncIdHelper; 560b57cec5SDimitry Andric 57e8d8bef9SDimitry Andric bool RecursiveCallsOnly = false; 580b57cec5SDimitry Andric bool DeduceSiblingCalls = false; 590b57cec5SDimitry Andric uint64_t CurrentMaxTSC = 0; 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric void recordLatency(int32_t FuncId, uint64_t Latency) { 620b57cec5SDimitry Andric FunctionLatencies[FuncId].push_back(Latency); 630b57cec5SDimitry Andric } 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric public: 660b57cec5SDimitry Andric explicit LatencyAccountant(FuncIdConversionHelper &FuncIdHelper, 67e8d8bef9SDimitry Andric bool RecursiveCallsOnly, bool DeduceSiblingCalls) 68e8d8bef9SDimitry Andric : FuncIdHelper(FuncIdHelper), RecursiveCallsOnly(RecursiveCallsOnly), 69e8d8bef9SDimitry Andric DeduceSiblingCalls(DeduceSiblingCalls) {} 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric const FunctionLatencyMap &getFunctionLatencies() const { 720b57cec5SDimitry Andric return FunctionLatencies; 730b57cec5SDimitry Andric } 740b57cec5SDimitry Andric 750b57cec5SDimitry Andric const PerThreadMinMaxTSCMap &getPerThreadMinMaxTSC() const { 760b57cec5SDimitry Andric return PerThreadMinMaxTSC; 770b57cec5SDimitry Andric } 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric const PerCPUMinMaxTSCMap &getPerCPUMinMaxTSC() const { 800b57cec5SDimitry Andric return PerCPUMinMaxTSC; 810b57cec5SDimitry Andric } 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric /// Returns false in case we fail to account the provided record. This happens 840b57cec5SDimitry Andric /// in the following cases: 850b57cec5SDimitry Andric /// 860b57cec5SDimitry Andric /// - An exit record does not match any entry records for the same function. 870b57cec5SDimitry Andric /// If we've been set to deduce sibling calls, we try walking up the stack 880b57cec5SDimitry Andric /// and recording times for the higher level functions. 890b57cec5SDimitry Andric /// - A record has a TSC that's before the latest TSC that has been 900b57cec5SDimitry Andric /// recorded. We still record the TSC for the min-max. 910b57cec5SDimitry Andric /// 920b57cec5SDimitry Andric bool accountRecord(const XRayRecord &Record); 930b57cec5SDimitry Andric 940b57cec5SDimitry Andric const PerThreadFunctionStackMap &getPerThreadFunctionStack() const { 950b57cec5SDimitry Andric return PerThreadFunctionStack; 960b57cec5SDimitry Andric } 970b57cec5SDimitry Andric 980b57cec5SDimitry Andric // Output Functions 990b57cec5SDimitry Andric // ================ 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric void exportStatsAsText(raw_ostream &OS, const XRayFileHeader &Header) const; 1020b57cec5SDimitry Andric void exportStatsAsCSV(raw_ostream &OS, const XRayFileHeader &Header) const; 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andric private: 1050b57cec5SDimitry Andric // Internal helper to implement common parts of the exportStatsAs... 1060b57cec5SDimitry Andric // functions. 1070b57cec5SDimitry Andric template <class F> void exportStats(const XRayFileHeader &Header, F fn) const; 1080b57cec5SDimitry Andric }; 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric } // namespace xray 1110b57cec5SDimitry Andric } // namespace llvm 1120b57cec5SDimitry Andric 1130b57cec5SDimitry Andric #endif // LLVM_TOOLS_LLVM_XRAY_XRAY_ACCOUNT_H 114