484 changes: 484 additions & 0 deletions llvm/tools/llvm-xray/xray-account.cc

Large diffs are not rendered by default.

104 changes: 104 additions & 0 deletions llvm/tools/llvm-xray/xray-account.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
//===- xray-account.h - XRay Function Call Accounting ---------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the interface for performing some basic function call
// accounting from an XRay trace.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TOOLS_LLVM_XRAY_XRAY_ACCOUNT_H
#define LLVM_TOOLS_LLVM_XRAY_XRAY_ACCOUNT_H

#include <map>
#include <utility>
#include <vector>

#include "func-id-helper.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/XRay/XRayRecord.h"

namespace llvm {
namespace xray {

class LatencyAccountant {
public:
typedef std::map<int32_t, std::vector<uint64_t>> FunctionLatencyMap;
typedef std::map<pid_t, std::pair<uint64_t, uint64_t>> PerThreadMinMaxTSCMap;
typedef std::map<uint8_t, std::pair<uint64_t, uint64_t>> PerCPUMinMaxTSCMap;
typedef std::vector<std::pair<int32_t, uint64_t>> FunctionStack;
typedef std::map<pid_t, FunctionStack> PerThreadFunctionStackMap;

private:
PerThreadFunctionStackMap PerThreadFunctionStack;
FunctionLatencyMap FunctionLatencies;
PerThreadMinMaxTSCMap PerThreadMinMaxTSC;
PerCPUMinMaxTSCMap PerCPUMinMaxTSC;
FuncIdConversionHelper &FuncIdHelper;

bool DeduceSiblingCalls = false;
uint64_t CurrentMaxTSC = 0;

void recordLatency(int32_t FuncId, uint64_t Latency) {
FunctionLatencies[FuncId].push_back(Latency);
}

public:
explicit LatencyAccountant(FuncIdConversionHelper &FuncIdHelper,
bool DeduceSiblingCalls)
: FuncIdHelper(FuncIdHelper), DeduceSiblingCalls(DeduceSiblingCalls) {}

const FunctionLatencyMap &getFunctionLatencies() const {
return FunctionLatencies;
}

const PerThreadMinMaxTSCMap &getPerThreadMinMaxTSC() const {
return PerThreadMinMaxTSC;
}

const PerCPUMinMaxTSCMap &getPerCPUMinMaxTSC() const {
return PerCPUMinMaxTSC;
}

/// Returns false in case we fail to account the provided record. This happens
/// in the following cases:
///
/// - An exit record does not match any entry records for the same function.
/// If we've been set to deduce sibling calls, we try walking up the stack
/// and recording times for the higher level functions.
/// - A record has a TSC that's before the latest TSC that has been
/// recorded. We still record the TSC for the min-max.
///
bool accountRecord(const XRayRecord &Record);

const FunctionStack *getThreadFunctionStack(pid_t TId) const {
auto I = PerThreadFunctionStack.find(TId);
if (I == PerThreadFunctionStack.end())
return nullptr;
return &I->second;
}

const PerThreadFunctionStackMap &getPerThreadFunctionStack() const {
return PerThreadFunctionStack;
}

// Output Functions
// ================

void exportStatsAsText(raw_ostream &OS, const XRayFileHeader &Header) const;
void exportStatsAsCSV(raw_ostream &OS, const XRayFileHeader &Header) const;

private:
// Internal helper to implement common parts of the exportStatsAs...
// functions.
template <class F> void exportStats(const XRayFileHeader &Header, F fn) const;
};

} // namespace xray
} // namespace llvm

#endif // LLVM_TOOLS_LLVM_XRAY_XRAY_ACCOUNT_H
102 changes: 102 additions & 0 deletions llvm/tools/llvm-xray/xray-record-yaml.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
//===- xray-record-yaml.h - XRay Record YAML Support Definitions ----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Types and traits specialisations for YAML I/O of XRay log entries.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TOOLS_LLVM_XRAY_XRAY_RECORD_YAML_H
#define LLVM_TOOLS_LLVM_XRAY_XRAY_RECORD_YAML_H

#include <type_traits>

#include "xray-record.h"
#include "llvm/Support/YAMLTraits.h"

namespace llvm {
namespace xray {

struct YAMLXRayFileHeader {
uint16_t Version;
uint16_t Type;
bool ConstantTSC;
bool NonstopTSC;
uint64_t CycleFrequency;
};

struct YAMLXRayRecord {
uint16_t RecordType;
uint8_t CPU;
RecordTypes Type;
int32_t FuncId;
std::string Function;
uint64_t TSC;
uint32_t TId;
};

struct YAMLXRayTrace {
YAMLXRayFileHeader Header;
std::vector<YAMLXRayRecord> Records;
};

using XRayRecordStorage =
std::aligned_storage<sizeof(XRayRecord), alignof(XRayRecord)>::type;

} // namespace xray

namespace yaml {

// YAML Traits
// -----------
template <> struct ScalarEnumerationTraits<xray::RecordTypes> {
static void enumeration(IO &IO, xray::RecordTypes &Type) {
IO.enumCase(Type, "function-enter", xray::RecordTypes::ENTER);
IO.enumCase(Type, "function-exit", xray::RecordTypes::EXIT);
}
};

template <> struct MappingTraits<xray::YAMLXRayFileHeader> {
static void mapping(IO &IO, xray::YAMLXRayFileHeader &Header) {
IO.mapRequired("version", Header.Version);
IO.mapRequired("type", Header.Type);
IO.mapRequired("constant-tsc", Header.ConstantTSC);
IO.mapRequired("nonstop-tsc", Header.NonstopTSC);
IO.mapRequired("cycle-frequency", Header.CycleFrequency);
}
};

template <> struct MappingTraits<xray::YAMLXRayRecord> {
static void mapping(IO &IO, xray::YAMLXRayRecord &Record) {
// FIXME: Make this type actually be descriptive
IO.mapRequired("type", Record.RecordType);
IO.mapRequired("func-id", Record.FuncId);
IO.mapOptional("function", Record.Function);
IO.mapRequired("cpu", Record.CPU);
IO.mapRequired("thread", Record.TId);
IO.mapRequired("kind", Record.Type);
IO.mapRequired("tsc", Record.TSC);
}

static constexpr bool flow = true;
};

template <> struct MappingTraits<xray::YAMLXRayTrace> {
static void mapping(IO &IO, xray::YAMLXRayTrace &Trace) {
// A trace file contains two parts, the header and the list of all the
// trace records.
IO.mapRequired("header", Trace.Header);
IO.mapRequired("records", Trace.Records);
}
};

} // namespace yaml
} // namespace llvm

LLVM_YAML_IS_SEQUENCE_VECTOR(xray::YAMLXRayRecord)

#endif // LLVM_TOOLS_LLVM_XRAY_XRAY_RECORD_YAML_H