Skip to content

Commit c4adfd4

Browse files
committed
Expose TimeTraceProfiler for overlapping spans
1 parent 23bc5b6 commit c4adfd4

File tree

2 files changed

+53
-32
lines changed

2 files changed

+53
-32
lines changed

llvm/include/llvm/Support/TimeProfiler.h

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ class raw_pwrite_stream;
8686
struct TimeTraceProfiler;
8787
TimeTraceProfiler *getTimeTraceProfilerInstance();
8888

89+
struct TimeTraceProfilerEntry;
90+
8991
/// Initialize the time trace profiler.
9092
/// This sets up the global \p TimeTraceProfilerInstance
9193
/// variable to be the profiler instance.
@@ -120,12 +122,15 @@ Error timeTraceProfilerWrite(StringRef PreferredFileName,
120122
/// Profiler copies the string data, so the pointers can be given into
121123
/// temporaries. Time sections can be hierarchical; every Begin must have a
122124
/// matching End pair but they can nest.
123-
void timeTraceProfilerBegin(StringRef Name, StringRef Detail);
124-
void timeTraceProfilerBegin(StringRef Name,
125-
llvm::function_ref<std::string()> Detail);
125+
TimeTraceProfilerEntry *timeTraceProfilerBegin(StringRef Name,
126+
StringRef Detail);
127+
TimeTraceProfilerEntry *
128+
timeTraceProfilerBegin(StringRef Name,
129+
llvm::function_ref<std::string()> Detail);
126130

127131
/// Manually end the last time section.
128132
void timeTraceProfilerEnd();
133+
void timeTraceProfilerEnd(TimeTraceProfilerEntry *E);
129134

130135
/// The TimeTraceScope is a helper class to call the begin and end functions
131136
/// of the time trace profiler. When the object is constructed, it begins
@@ -141,20 +146,23 @@ struct TimeTraceScope {
141146

142147
TimeTraceScope(StringRef Name) {
143148
if (getTimeTraceProfilerInstance() != nullptr)
144-
timeTraceProfilerBegin(Name, StringRef(""));
149+
Entry = timeTraceProfilerBegin(Name, StringRef(""));
145150
}
146151
TimeTraceScope(StringRef Name, StringRef Detail) {
147152
if (getTimeTraceProfilerInstance() != nullptr)
148-
timeTraceProfilerBegin(Name, Detail);
153+
Entry = timeTraceProfilerBegin(Name, Detail);
149154
}
150155
TimeTraceScope(StringRef Name, llvm::function_ref<std::string()> Detail) {
151156
if (getTimeTraceProfilerInstance() != nullptr)
152-
timeTraceProfilerBegin(Name, Detail);
157+
Entry = timeTraceProfilerBegin(Name, Detail);
153158
}
154159
~TimeTraceScope() {
155160
if (getTimeTraceProfilerInstance() != nullptr)
156-
timeTraceProfilerEnd();
161+
timeTraceProfilerEnd(Entry);
157162
}
163+
164+
private:
165+
TimeTraceProfilerEntry *Entry = nullptr;
158166
};
159167

160168
} // end namespace llvm

llvm/lib/Support/TimeProfiler.cpp

Lines changed: 38 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
#include "llvm/Support/TimeProfiler.h"
14+
#include "llvm/ADT/STLExtras.h"
1415
#include "llvm/ADT/STLFunctionalExtras.h"
1516
#include "llvm/ADT/StringMap.h"
1617
#include "llvm/Support/JSON.h"
@@ -20,6 +21,7 @@
2021
#include <algorithm>
2122
#include <cassert>
2223
#include <chrono>
24+
#include <memory>
2325
#include <mutex>
2426
#include <string>
2527
#include <vector>
@@ -64,8 +66,10 @@ using CountAndDurationType = std::pair<size_t, DurationType>;
6466
using NameAndCountAndDurationType =
6567
std::pair<std::string, CountAndDurationType>;
6668

69+
} // anonymous namespace
70+
6771
/// Represents an open or completed time section entry to be captured.
68-
struct TimeTraceProfilerEntry {
72+
struct llvm::TimeTraceProfilerEntry {
6973
const TimePointType Start;
7074
TimePointType End;
7175
const std::string Name;
@@ -92,8 +96,6 @@ struct TimeTraceProfilerEntry {
9296
}
9397
};
9498

95-
} // anonymous namespace
96-
9799
struct llvm::TimeTraceProfiler {
98100
TimeTraceProfiler(unsigned TimeTraceGranularity = 0, StringRef ProcName = "")
99101
: BeginningOfTime(system_clock::now()), StartTime(ClockType::now()),
@@ -102,23 +104,22 @@ struct llvm::TimeTraceProfiler {
102104
llvm::get_thread_name(ThreadName);
103105
}
104106

105-
void begin(std::string Name, llvm::function_ref<std::string()> Detail) {
106-
Stack.emplace_back(ClockType::now(), TimePointType(), std::move(Name),
107-
Detail());
107+
TimeTraceProfilerEntry *begin(std::string Name,
108+
llvm::function_ref<std::string()> Detail) {
109+
Stack.emplace_back(std::make_unique<TimeTraceProfilerEntry>(
110+
ClockType::now(), TimePointType(), std::move(Name), Detail()));
111+
return Stack.back().get();
108112
}
109113

110114
void end() {
115+
TimeTraceProfilerEntry *E = Stack.back().get();
116+
end(*E);
117+
}
118+
119+
void end(TimeTraceProfilerEntry &E) {
111120
assert(!Stack.empty() && "Must call begin() first");
112-
TimeTraceProfilerEntry &E = Stack.back();
113121
E.End = ClockType::now();
114122

115-
// Check that end times monotonically increase.
116-
assert((Entries.empty() ||
117-
(E.getFlameGraphStartUs(StartTime) + E.getFlameGraphDurUs() >=
118-
Entries.back().getFlameGraphStartUs(StartTime) +
119-
Entries.back().getFlameGraphDurUs())) &&
120-
"TimeProfiler scope ended earlier than previous scope");
121-
122123
// Calculate duration at full precision for overall counts.
123124
DurationType Duration = E.End - E.Start;
124125

@@ -132,15 +133,18 @@ struct llvm::TimeTraceProfiler {
132133
// happens to be the ones that don't have any currently open entries above
133134
// itself.
134135
if (llvm::none_of(llvm::drop_begin(llvm::reverse(Stack)),
135-
[&](const TimeTraceProfilerEntry &Val) {
136-
return Val.Name == E.Name;
136+
[&](const std::unique_ptr<TimeTraceProfilerEntry> &Val) {
137+
return Val->Name == E.Name;
137138
})) {
138139
auto &CountAndTotal = CountAndTotalPerName[E.Name];
139140
CountAndTotal.first++;
140141
CountAndTotal.second += Duration;
141-
}
142+
};
142143

143-
Stack.pop_back();
144+
llvm::erase_if(Stack,
145+
[&](const std::unique_ptr<TimeTraceProfilerEntry> &Val) {
146+
return Val.get() == &E;
147+
});
144148
}
145149

146150
// Write events from this TimeTraceProfilerInstance and
@@ -269,7 +273,7 @@ struct llvm::TimeTraceProfiler {
269273
J.objectEnd();
270274
}
271275

272-
SmallVector<TimeTraceProfilerEntry, 16> Stack;
276+
SmallVector<std::unique_ptr<TimeTraceProfilerEntry>, 16> Stack;
273277
SmallVector<TimeTraceProfilerEntry, 128> Entries;
274278
StringMap<CountAndDurationType> CountAndTotalPerName;
275279
// System clock time when the session was begun.
@@ -341,19 +345,28 @@ Error llvm::timeTraceProfilerWrite(StringRef PreferredFileName,
341345
return Error::success();
342346
}
343347

344-
void llvm::timeTraceProfilerBegin(StringRef Name, StringRef Detail) {
348+
TimeTraceProfilerEntry *llvm::timeTraceProfilerBegin(StringRef Name,
349+
StringRef Detail) {
345350
if (TimeTraceProfilerInstance != nullptr)
346-
TimeTraceProfilerInstance->begin(std::string(Name),
347-
[&]() { return std::string(Detail); });
351+
return TimeTraceProfilerInstance->begin(
352+
std::string(Name), [&]() { return std::string(Detail); });
353+
return nullptr;
348354
}
349355

350-
void llvm::timeTraceProfilerBegin(StringRef Name,
351-
llvm::function_ref<std::string()> Detail) {
356+
TimeTraceProfilerEntry *
357+
llvm::timeTraceProfilerBegin(StringRef Name,
358+
llvm::function_ref<std::string()> Detail) {
352359
if (TimeTraceProfilerInstance != nullptr)
353-
TimeTraceProfilerInstance->begin(std::string(Name), Detail);
360+
return TimeTraceProfilerInstance->begin(std::string(Name), Detail);
361+
return nullptr;
354362
}
355363

356364
void llvm::timeTraceProfilerEnd() {
357365
if (TimeTraceProfilerInstance != nullptr)
358366
TimeTraceProfilerInstance->end();
359367
}
368+
369+
void llvm::timeTraceProfilerEnd(TimeTraceProfilerEntry *E) {
370+
if (TimeTraceProfilerInstance != nullptr)
371+
TimeTraceProfilerInstance->end(*E);
372+
}

0 commit comments

Comments
 (0)