File indexing completed on 2024-05-05 05:44:15

0001 /*
0002     SPDX-FileCopyrightText: 2015-2020 Milian Wolff <mail@milianw.de>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-or-later
0005 */
0006 
0007 #ifndef ACCUMULATEDTRACEDATA_H
0008 #define ACCUMULATEDTRACEDATA_H
0009 
0010 #include <iosfwd>
0011 #include <tuple>
0012 #include <vector>
0013 
0014 #include <fstream>
0015 
0016 #include <boost/iostreams/filtering_stream.hpp>
0017 
0018 #include "allocationdata.h"
0019 #include "filterparameters.h"
0020 #include "util/indices.h"
0021 
0022 struct Frame
0023 {
0024     FunctionIndex functionIndex;
0025     FileIndex fileIndex;
0026     int line = 0;
0027 
0028     bool operator==(const Frame& rhs) const
0029     {
0030         return functionIndex == rhs.functionIndex && fileIndex == rhs.fileIndex && line == rhs.line;
0031     }
0032 
0033     bool operator<(const Frame& rhs) const
0034     {
0035         return std::tie(functionIndex, fileIndex, line) < std::tie(rhs.functionIndex, rhs.fileIndex, rhs.line);
0036     }
0037 };
0038 
0039 struct InstructionPointer
0040 {
0041     uint64_t instructionPointer = 0;
0042     ModuleIndex moduleIndex;
0043     Frame frame;
0044     std::vector<Frame> inlined;
0045 
0046     bool compareWithoutAddress(const InstructionPointer& other) const
0047     {
0048         return std::tie(moduleIndex, frame) < std::tie(other.moduleIndex, other.frame);
0049     }
0050 
0051     bool equalWithoutAddress(const InstructionPointer& other) const
0052     {
0053         return moduleIndex == other.moduleIndex && frame == other.frame;
0054     }
0055 };
0056 
0057 struct TraceNode
0058 {
0059     IpIndex ipIndex;
0060     TraceIndex parentIndex;
0061 };
0062 
0063 struct Allocation : public AllocationData
0064 {
0065     // backtrace entry point
0066     TraceIndex traceIndex;
0067 };
0068 
0069 /**
0070  * Information for a single call to an allocation function.
0071  */
0072 struct AllocationInfo
0073 {
0074     uint64_t size = 0;
0075     // index into AccumulatedTraceData::allocations
0076     AllocationIndex allocationIndex;
0077     bool operator==(const AllocationInfo& rhs) const
0078     {
0079         return rhs.allocationIndex == allocationIndex && rhs.size == size;
0080     }
0081 };
0082 
0083 struct Suppression;
0084 
0085 struct AccumulatedTraceData
0086 {
0087     AccumulatedTraceData();
0088     virtual ~AccumulatedTraceData();
0089 
0090     enum ParsePass
0091     {
0092         // find time of total peak cost
0093         FirstPass,
0094         // parse individual allocations
0095         SecondPass,
0096         // GUI only: graph-building
0097         ThirdPass
0098     };
0099 
0100     virtual void handleTimeStamp(int64_t oldStamp, int64_t newStamp, bool isFinalTimeStamp, const ParsePass pass) = 0;
0101     virtual void handleAllocation(const AllocationInfo& info, const AllocationInfoIndex index) = 0;
0102     virtual void handleDebuggee(const char* command) = 0;
0103 
0104     const std::string& stringify(const StringIndex stringId) const;
0105 
0106     std::string prettyFunction(const std::string& function) const;
0107 
0108     bool read(const std::string& inputFile, bool isReparsing);
0109     bool read(const std::string& inputFile, const ParsePass pass, bool isReparsing);
0110     bool read(boost::iostreams::filtering_istream& in, const ParsePass pass, bool isReparsing);
0111 
0112     void diff(const AccumulatedTraceData& base);
0113 
0114     bool shortenTemplates = false;
0115     bool fromAttached = false;
0116     FilterParameters filterParameters;
0117 
0118     std::vector<Allocation> allocations;
0119     AllocationData totalCost;
0120     int64_t totalTime = 0;
0121     int64_t peakTime = 0;
0122     int64_t peakRSS = 0;
0123 
0124     struct SystemInfo
0125     {
0126         int64_t pages = 0;
0127         int64_t pageSize = 0;
0128     };
0129     SystemInfo systemInfo;
0130 
0131     // our indices are sequentially increasing thus a new allocation can only ever
0132     // occur with an index larger than any other we encountered so far
0133     // this can be used to our advantage in speeding up the mapToAllocationIndex calls.
0134     TraceIndex m_maxAllocationTraceIndex;
0135     AllocationIndex m_maxAllocationIndex;
0136     // we don't want to shuffle allocations around, so instead keep a secondary
0137     // vector around for efficient index lookup
0138     std::vector<std::pair<TraceIndex, AllocationIndex>> traceIndexToAllocationIndex;
0139 
0140     /// find and return the index into the @c allocations vector for the given trace index.
0141     /// if the trace index wasn't mapped before, an empty Allocation will be added
0142     /// and its index returned.
0143     AllocationIndex mapToAllocationIndex(const TraceIndex traceIndex);
0144 
0145     const InstructionPointer& findIp(const IpIndex ipIndex) const;
0146 
0147     TraceNode findTrace(const TraceIndex traceIndex) const;
0148 
0149     bool isStopIndex(const StringIndex index) const;
0150 
0151     // indices of functions that should stop the backtrace, e.g. main or static
0152     // initialization
0153     std::vector<StringIndex> stopIndices;
0154     std::vector<InstructionPointer> instructionPointers;
0155     std::vector<TraceNode> traces;
0156     std::vector<std::string> strings;
0157     std::vector<IpIndex> opNewIpIndices;
0158 
0159     std::vector<AllocationInfo> allocationInfos;
0160 
0161     struct ParsingState
0162     {
0163         int64_t fileSize = 0; // bytes
0164         int64_t readCompressedByte = 0;
0165         int64_t readUncompressedByte = 0;
0166         int64_t timestamp = 0; // ms
0167         ParsePass pass = ParsePass::FirstPass;
0168         bool reparsing = false;
0169     };
0170 
0171     ParsingState parsingState;
0172 
0173     void applyLeakSuppressions();
0174     std::vector<Suppression> suppressions;
0175     int64_t totalLeakedSuppressed = 0;
0176 };
0177 
0178 #endif // ACCUMULATEDTRACEDATA_H