Skip to content

Commit

Permalink
[XRay] Use FDR Records+Visitors for Trace Loading
Browse files Browse the repository at this point in the history
Summary:
In this change, we overhaul the implementation for loading
`llvm::xray::Trace` objects from files by using the combination of
specific FDR Record types and visitors breaking up the logic to
reconstitute an execution trace from flight-data recorder mode traces.

This change allows us to handle out-of-temporal order blocks as written
in files, and more consistently recreate an execution trace spanning
multiple blocks and threads. To do this, we use the `WallclockRecord`
associated with each block to maintain temporal order of blocks, before
attempting to recreate an execution trace.

The new addition in this change is the `TraceExpander` type which can be
thought of as a decompression/decoding routine. This allows us to
maintain the state of an execution environment (thread+process) and
create `XRayRecord` instances that fit nicely into the `Trace`
container. We don't have a specific unit test for the TraceExpander
type, since the end-to-end tests for the `llvm-xray convert` tools
already cover precisely this codepath.

This change completes the refactoring started with D50441.

Depends on D51911.

Reviewers: mboerger, eizan

Subscribers: mgorny, hiraditya, mgrang, llvm-commits

Differential Revision: https://reviews.llvm.org/D51912

llvm-svn: 341906
  • Loading branch information
deanberris committed Sep 11, 2018
1 parent d2c5040 commit 985c2b9
Show file tree
Hide file tree
Showing 6 changed files with 230 additions and 546 deletions.
3 changes: 2 additions & 1 deletion llvm/include/llvm/XRay/BlockIndexer.h
Expand Up @@ -29,6 +29,7 @@ class BlockIndexer : public RecordVisitor {
struct Block {
uint64_t ProcessID;
int32_t ThreadID;
WallclockRecord *WallclockTime;
std::vector<Record *> Records;
};

Expand All @@ -41,7 +42,7 @@ class BlockIndexer : public RecordVisitor {
enum class State : unsigned { SeekExtents, ExtentsFound, ThreadIDFound };

State CurrentState = State::SeekExtents;
Block CurrentBlock{0, 0, {}};
Block CurrentBlock{0, 0, nullptr, {}};

public:
explicit BlockIndexer(Index &I) : RecordVisitor(), Indices(I) {}
Expand Down
61 changes: 61 additions & 0 deletions llvm/include/llvm/XRay/FDRTraceExpander.h
@@ -0,0 +1,61 @@
//===- FDRTraceExpander.h - XRay FDR Mode Log Expander --------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// We define an FDR record visitor which can re-constitute XRayRecord instances
// from a sequence of FDR mode records in arrival order into a collection.
//
//===----------------------------------------------------------------------===//
#ifndef INCLUDE_LLVM_XRAY_FDRTRACEEXPANDER_H_
#define INCLUDE_LLVM_XRAY_FDRTRACEEXPANDER_H_

#include "llvm/ADT/STLExtras.h"
#include "llvm/XRay/FDRRecords.h"
#include "llvm/XRay/XRayRecord.h"

namespace llvm {
namespace xray {

class TraceExpander : public RecordVisitor {
// Type-erased callback for handling individual XRayRecord instances.
function_ref<void(const XRayRecord &)> C;
int32_t PID = 0;
int32_t TID = 0;
uint64_t BaseTSC = 0;
XRayRecord CurrentRecord{};
uint16_t CPUId = 0;
uint16_t LogVersion = 0;
bool BuildingFunction = false;
bool IgnoringRecords = false;

void resetCurrentRecord();

public:
explicit TraceExpander(function_ref<void(const XRayRecord &)> F, uint16_t L)
: RecordVisitor(), C(std::move(F)), LogVersion(L) {}

Error visit(BufferExtents &) override;
Error visit(WallclockRecord &) override;
Error visit(NewCPUIDRecord &) override;
Error visit(TSCWrapRecord &) override;
Error visit(CustomEventRecord &) override;
Error visit(CallArgRecord &) override;
Error visit(PIDRecord &) override;
Error visit(NewBufferRecord &) override;
Error visit(EndBufferRecord &) override;
Error visit(FunctionRecord &) override;

// Must be called after all the records have been processed, to handle the
// most recent record generated.
Error flush();
};

} // namespace xray
} // namespace llvm

#endif // INCLUDE_LLVM_XRAY_FDRTRACEEXPANDER_H_
4 changes: 4 additions & 0 deletions llvm/lib/XRay/BlockIndexer.cpp
Expand Up @@ -22,9 +22,11 @@ Error BlockIndexer::visit(BufferExtents &) {
std::tie(It, std::ignore) =
Indices.insert({{CurrentBlock.ProcessID, CurrentBlock.ThreadID}, {}});
It->second.push_back({CurrentBlock.ProcessID, CurrentBlock.ThreadID,
CurrentBlock.WallclockTime,
std::move(CurrentBlock.Records)});
CurrentBlock.ProcessID = 0;
CurrentBlock.ThreadID = 0;
CurrentBlock.WallclockTime = nullptr;
CurrentBlock.Records = {};
}
CurrentState = State::ExtentsFound;
Expand All @@ -33,6 +35,7 @@ Error BlockIndexer::visit(BufferExtents &) {

Error BlockIndexer::visit(WallclockRecord &R) {
CurrentBlock.Records.push_back(&R);
CurrentBlock.WallclockTime = &R;
return Error::success();
}

Expand Down Expand Up @@ -86,6 +89,7 @@ Error BlockIndexer::flush() {
std::tie(It, std::ignore) =
Indices.insert({{CurrentBlock.ProcessID, CurrentBlock.ThreadID}, {}});
It->second.push_back({CurrentBlock.ProcessID, CurrentBlock.ThreadID,
CurrentBlock.WallclockTime,
std::move(CurrentBlock.Records)});
CurrentBlock.ProcessID = 0;
CurrentBlock.ThreadID = 0;
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/XRay/CMakeLists.txt
Expand Up @@ -4,6 +4,7 @@ add_llvm_library(LLVMXRay
BlockVerifier.cpp
FDRRecordProducer.cpp
FDRRecords.cpp
FDRTraceExpander.cpp
FDRTraceWriter.cpp
FileHeaderReader.cpp
InstrumentationMap.cpp
Expand Down
92 changes: 92 additions & 0 deletions llvm/lib/XRay/FDRTraceExpander.cpp
@@ -0,0 +1,92 @@
//===- FDRTraceExpander.cpp -----------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/XRay/FDRTraceExpander.h"

namespace llvm {
namespace xray {

void TraceExpander::resetCurrentRecord() {
if (BuildingFunction)
C(CurrentRecord);
BuildingFunction = false;
CurrentRecord.CallArgs.clear();
}

Error TraceExpander::visit(BufferExtents &) {
resetCurrentRecord();
return Error::success();
}

Error TraceExpander::visit(WallclockRecord &) { return Error::success(); }

Error TraceExpander::visit(NewCPUIDRecord &R) {
CPUId = R.cpuid();
BaseTSC = R.tsc();
return Error::success();
}

Error TraceExpander::visit(TSCWrapRecord &R) {
BaseTSC = R.tsc();
return Error::success();
}

Error TraceExpander::visit(CustomEventRecord &) {
// TODO: Support custom event records in the future.
resetCurrentRecord();
return Error::success();
}

Error TraceExpander::visit(CallArgRecord &R) {
CurrentRecord.CallArgs.push_back(R.arg());
CurrentRecord.Type = RecordTypes::ENTER_ARG;
return Error::success();
}

Error TraceExpander::visit(PIDRecord &R) {
PID = R.pid();
return Error::success();
}

Error TraceExpander::visit(NewBufferRecord &R) {
if (IgnoringRecords)
IgnoringRecords = false;
TID = R.tid();
if (LogVersion == 2)
PID = R.tid();
return Error::success();
}

Error TraceExpander::visit(EndBufferRecord &) {
IgnoringRecords = true;
resetCurrentRecord();
return Error::success();
}

Error TraceExpander::visit(FunctionRecord &R) {
resetCurrentRecord();
if (!IgnoringRecords) {
BaseTSC += R.delta();
CurrentRecord.Type = R.recordType();
CurrentRecord.FuncId = R.functionId();
CurrentRecord.TSC = BaseTSC;
CurrentRecord.PId = PID;
CurrentRecord.TId = TID;
CurrentRecord.CPU = CPUId;
BuildingFunction = true;
}
return Error::success();
}

Error TraceExpander::flush() {
resetCurrentRecord();
return Error::success();
}

} // namespace xray
} // namespace llvm

0 comments on commit 985c2b9

Please sign in to comment.