aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Support/TimeProfiler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Support/TimeProfiler.cpp')
-rw-r--r--llvm/lib/Support/TimeProfiler.cpp105
1 files changed, 67 insertions, 38 deletions
diff --git a/llvm/lib/Support/TimeProfiler.cpp b/llvm/lib/Support/TimeProfiler.cpp
index 9380fa01c84a..4d625b3eb5b1 100644
--- a/llvm/lib/Support/TimeProfiler.cpp
+++ b/llvm/lib/Support/TimeProfiler.cpp
@@ -14,7 +14,6 @@
#include "llvm/ADT/STLFunctionalExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/JSON.h"
-#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Threading.h"
@@ -25,13 +24,30 @@
#include <string>
#include <vector>
-using namespace std::chrono;
using namespace llvm;
-static std::mutex Mu;
-// List of all instances
-static ManagedStatic<std::vector<TimeTraceProfiler *>>
- ThreadTimeTraceProfilerInstances; // GUARDED_BY(Mu)
+namespace {
+
+using std::chrono::duration;
+using std::chrono::duration_cast;
+using std::chrono::microseconds;
+using std::chrono::steady_clock;
+using std::chrono::system_clock;
+using std::chrono::time_point;
+using std::chrono::time_point_cast;
+
+struct TimeTraceProfilerInstances {
+ std::mutex Lock;
+ std::vector<TimeTraceProfiler *> List;
+};
+
+TimeTraceProfilerInstances &getTimeTraceProfilerInstances() {
+ static TimeTraceProfilerInstances Instances;
+ return Instances;
+}
+
+} // anonymous namespace
+
// Per Thread instance
static LLVM_THREAD_LOCAL TimeTraceProfiler *TimeTraceProfilerInstance = nullptr;
@@ -39,57 +55,62 @@ TimeTraceProfiler *llvm::getTimeTraceProfilerInstance() {
return TimeTraceProfilerInstance;
}
-typedef duration<steady_clock::rep, steady_clock::period> DurationType;
-typedef time_point<steady_clock> TimePointType;
-typedef std::pair<size_t, DurationType> CountAndDurationType;
-typedef std::pair<std::string, CountAndDurationType>
- NameAndCountAndDurationType;
-
namespace {
-struct Entry {
+
+using ClockType = steady_clock;
+using TimePointType = time_point<ClockType>;
+using DurationType = duration<ClockType::rep, ClockType::period>;
+using CountAndDurationType = std::pair<size_t, DurationType>;
+using NameAndCountAndDurationType =
+ std::pair<std::string, CountAndDurationType>;
+
+/// Represents an open or completed time section entry to be captured.
+struct TimeTraceProfilerEntry {
const TimePointType Start;
TimePointType End;
const std::string Name;
const std::string Detail;
- Entry(TimePointType &&S, TimePointType &&E, std::string &&N, std::string &&Dt)
+ TimeTraceProfilerEntry(TimePointType &&S, TimePointType &&E, std::string &&N,
+ std::string &&Dt)
: Start(std::move(S)), End(std::move(E)), Name(std::move(N)),
Detail(std::move(Dt)) {}
// Calculate timings for FlameGraph. Cast time points to microsecond precision
- // rather than casting duration. This avoid truncation issues causing inner
+ // rather than casting duration. This avoids truncation issues causing inner
// scopes overruning outer scopes.
- steady_clock::rep getFlameGraphStartUs(TimePointType StartTime) const {
+ ClockType::rep getFlameGraphStartUs(TimePointType StartTime) const {
return (time_point_cast<microseconds>(Start) -
time_point_cast<microseconds>(StartTime))
.count();
}
- steady_clock::rep getFlameGraphDurUs() const {
+ ClockType::rep getFlameGraphDurUs() const {
return (time_point_cast<microseconds>(End) -
time_point_cast<microseconds>(Start))
.count();
}
};
-} // namespace
+
+} // anonymous namespace
struct llvm::TimeTraceProfiler {
TimeTraceProfiler(unsigned TimeTraceGranularity = 0, StringRef ProcName = "")
- : BeginningOfTime(system_clock::now()), StartTime(steady_clock::now()),
+ : BeginningOfTime(system_clock::now()), StartTime(ClockType::now()),
ProcName(ProcName), Pid(sys::Process::getProcessId()),
Tid(llvm::get_threadid()), TimeTraceGranularity(TimeTraceGranularity) {
llvm::get_thread_name(ThreadName);
}
void begin(std::string Name, llvm::function_ref<std::string()> Detail) {
- Stack.emplace_back(steady_clock::now(), TimePointType(), std::move(Name),
+ Stack.emplace_back(ClockType::now(), TimePointType(), std::move(Name),
Detail());
}
void end() {
assert(!Stack.empty() && "Must call begin() first");
- Entry &E = Stack.back();
- E.End = steady_clock::now();
+ TimeTraceProfilerEntry &E = Stack.back();
+ E.End = ClockType::now();
// Check that end times monotonically increase.
assert((Entries.empty() ||
@@ -111,7 +132,9 @@ struct llvm::TimeTraceProfiler {
// happens to be the ones that don't have any currently open entries above
// itself.
if (llvm::none_of(llvm::drop_begin(llvm::reverse(Stack)),
- [&](const Entry &Val) { return Val.Name == E.Name; })) {
+ [&](const TimeTraceProfilerEntry &Val) {
+ return Val.Name == E.Name;
+ })) {
auto &CountAndTotal = CountAndTotalPerName[E.Name];
CountAndTotal.first++;
CountAndTotal.second += Duration;
@@ -124,10 +147,11 @@ struct llvm::TimeTraceProfiler {
// ThreadTimeTraceProfilerInstances.
void write(raw_pwrite_stream &OS) {
// Acquire Mutex as reading ThreadTimeTraceProfilerInstances.
- std::lock_guard<std::mutex> Lock(Mu);
+ auto &Instances = getTimeTraceProfilerInstances();
+ std::lock_guard<std::mutex> Lock(Instances.Lock);
assert(Stack.empty() &&
"All profiler sections should be ended when calling write");
- assert(llvm::all_of(*ThreadTimeTraceProfilerInstances,
+ assert(llvm::all_of(Instances.List,
[](const auto &TTP) { return TTP->Stack.empty(); }) &&
"All profiler sections should be ended when calling write");
@@ -153,17 +177,17 @@ struct llvm::TimeTraceProfiler {
}
});
};
- for (const Entry &E : Entries)
+ for (const TimeTraceProfilerEntry &E : Entries)
writeEvent(E, this->Tid);
- for (const TimeTraceProfiler *TTP : *ThreadTimeTraceProfilerInstances)
- for (const Entry &E : TTP->Entries)
+ for (const TimeTraceProfiler *TTP : Instances.List)
+ for (const TimeTraceProfilerEntry &E : TTP->Entries)
writeEvent(E, TTP->Tid);
// Emit totals by section name as additional "thread" events, sorted from
// longest one.
// Find highest used thread id.
uint64_t MaxTid = this->Tid;
- for (const TimeTraceProfiler *TTP : *ThreadTimeTraceProfilerInstances)
+ for (const TimeTraceProfiler *TTP : Instances.List)
MaxTid = std::max(MaxTid, TTP->Tid);
// Combine all CountAndTotalPerName from threads into one.
@@ -177,7 +201,7 @@ struct llvm::TimeTraceProfiler {
};
for (const auto &Stat : CountAndTotalPerName)
combineStat(Stat);
- for (const TimeTraceProfiler *TTP : *ThreadTimeTraceProfilerInstances)
+ for (const TimeTraceProfiler *TTP : Instances.List)
for (const auto &Stat : TTP->CountAndTotalPerName)
combineStat(Stat);
@@ -228,7 +252,7 @@ struct llvm::TimeTraceProfiler {
writeMetadataEvent("process_name", Tid, ProcName);
writeMetadataEvent("thread_name", Tid, ThreadName);
- for (const TimeTraceProfiler *TTP : *ThreadTimeTraceProfilerInstances)
+ for (const TimeTraceProfiler *TTP : Instances.List)
writeMetadataEvent("thread_name", TTP->Tid, TTP->ThreadName);
J.arrayEnd();
@@ -245,10 +269,12 @@ struct llvm::TimeTraceProfiler {
J.objectEnd();
}
- SmallVector<Entry, 16> Stack;
- SmallVector<Entry, 128> Entries;
+ SmallVector<TimeTraceProfilerEntry, 16> Stack;
+ SmallVector<TimeTraceProfilerEntry, 128> Entries;
StringMap<CountAndDurationType> CountAndTotalPerName;
+ // System clock time when the session was begun.
const time_point<system_clock> BeginningOfTime;
+ // Profiling clock time when the session was begun.
const TimePointType StartTime;
const std::string ProcName;
const sys::Process::Pid Pid;
@@ -272,17 +298,20 @@ void llvm::timeTraceProfilerInitialize(unsigned TimeTraceGranularity,
void llvm::timeTraceProfilerCleanup() {
delete TimeTraceProfilerInstance;
TimeTraceProfilerInstance = nullptr;
- std::lock_guard<std::mutex> Lock(Mu);
- for (auto *TTP : *ThreadTimeTraceProfilerInstances)
+
+ auto &Instances = getTimeTraceProfilerInstances();
+ std::lock_guard<std::mutex> Lock(Instances.Lock);
+ for (auto *TTP : Instances.List)
delete TTP;
- ThreadTimeTraceProfilerInstances->clear();
+ Instances.List.clear();
}
// Finish TimeTraceProfilerInstance on a worker thread.
// This doesn't remove the instance, just moves the pointer to global vector.
void llvm::timeTraceProfilerFinishThread() {
- std::lock_guard<std::mutex> Lock(Mu);
- ThreadTimeTraceProfilerInstances->push_back(TimeTraceProfilerInstance);
+ auto &Instances = getTimeTraceProfilerInstances();
+ std::lock_guard<std::mutex> Lock(Instances.Lock);
+ Instances.List.push_back(TimeTraceProfilerInstance);
TimeTraceProfilerInstance = nullptr;
}