11
11
// ===----------------------------------------------------------------------===//
12
12
13
13
#include " llvm/Support/TimeProfiler.h"
14
+ #include " llvm/ADT/STLExtras.h"
14
15
#include " llvm/ADT/STLFunctionalExtras.h"
15
16
#include " llvm/ADT/StringMap.h"
16
17
#include " llvm/Support/JSON.h"
20
21
#include < algorithm>
21
22
#include < cassert>
22
23
#include < chrono>
24
+ #include < memory>
23
25
#include < mutex>
24
26
#include < string>
25
27
#include < vector>
@@ -64,17 +66,19 @@ using CountAndDurationType = std::pair<size_t, DurationType>;
64
66
using NameAndCountAndDurationType =
65
67
std::pair<std::string, CountAndDurationType>;
66
68
69
+ } // anonymous namespace
70
+
67
71
// / Represents an open or completed time section entry to be captured.
68
- struct TimeTraceProfilerEntry {
72
+ struct llvm :: TimeTraceProfilerEntry {
69
73
const TimePointType Start;
70
74
TimePointType End;
71
75
const std::string Name;
72
76
const std::string Detail;
73
-
77
+ const bool AsyncEvent = false ;
74
78
TimeTraceProfilerEntry (TimePointType &&S, TimePointType &&E, std::string &&N,
75
- std::string &&Dt)
79
+ std::string &&Dt, bool Ae )
76
80
: Start(std::move(S)), End(std::move(E)), Name(std::move(N)),
77
- Detail (std::move(Dt)) {}
81
+ Detail (std::move(Dt)), AsyncEvent(Ae) {}
78
82
79
83
// Calculate timings for FlameGraph. Cast time points to microsecond precision
80
84
// rather than casting duration. This avoids truncation issues causing inner
@@ -92,8 +96,6 @@ struct TimeTraceProfilerEntry {
92
96
}
93
97
};
94
98
95
- } // anonymous namespace
96
-
97
99
struct llvm ::TimeTraceProfiler {
98
100
TimeTraceProfiler (unsigned TimeTraceGranularity = 0 , StringRef ProcName = " " )
99
101
: BeginningOfTime(system_clock::now()), StartTime(ClockType::now()),
@@ -102,22 +104,23 @@ struct llvm::TimeTraceProfiler {
102
104
llvm::get_thread_name (ThreadName);
103
105
}
104
106
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
+ bool AsyncEvent = false) {
110
+ Stack.emplace_back (std::make_unique<TimeTraceProfilerEntry>(
111
+ ClockType::now (), TimePointType (), std::move (Name), Detail (),
112
+ AsyncEvent));
113
+ return Stack.back ().get ();
108
114
}
109
115
110
116
void end () {
111
117
assert (!Stack.empty () && " Must call begin() first" );
112
- TimeTraceProfilerEntry &E = Stack.back ();
113
- E. End = ClockType::now ();
118
+ end (* Stack.back (). get () );
119
+ }
114
120
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
+ void end (TimeTraceProfilerEntry &E) {
122
+ assert (!Stack.empty () && " Must call begin() first" );
123
+ E.End = ClockType::now ();
121
124
122
125
// Calculate duration at full precision for overall counts.
123
126
DurationType Duration = E.End - E.Start ;
@@ -132,15 +135,18 @@ struct llvm::TimeTraceProfiler {
132
135
// happens to be the ones that don't have any currently open entries above
133
136
// itself.
134
137
if (llvm::none_of (llvm::drop_begin (llvm::reverse (Stack)),
135
- [&](const TimeTraceProfilerEntry &Val) {
136
- return Val. Name == E.Name ;
138
+ [&](const std::unique_ptr< TimeTraceProfilerEntry> &Val) {
139
+ return Val-> Name == E.Name ;
137
140
})) {
138
141
auto &CountAndTotal = CountAndTotalPerName[E.Name ];
139
142
CountAndTotal.first ++;
140
143
CountAndTotal.second += Duration;
141
- }
144
+ };
142
145
143
- Stack.pop_back ();
146
+ llvm::erase_if (Stack,
147
+ [&](const std::unique_ptr<TimeTraceProfilerEntry> &Val) {
148
+ return Val.get () == &E;
149
+ });
144
150
}
145
151
146
152
// Write events from this TimeTraceProfilerInstance and
@@ -168,14 +174,32 @@ struct llvm::TimeTraceProfiler {
168
174
J.object ([&] {
169
175
J.attribute (" pid" , Pid);
170
176
J.attribute (" tid" , int64_t (Tid));
171
- J.attribute (" ph" , " X" );
172
177
J.attribute (" ts" , StartUs);
173
- J.attribute (" dur" , DurUs);
178
+ if (E.AsyncEvent ) {
179
+ J.attribute (" cat" , E.Name );
180
+ J.attribute (" ph" , " b" );
181
+ J.attribute (" id" , 0 );
182
+ } else {
183
+ J.attribute (" ph" , " X" );
184
+ J.attribute (" dur" , DurUs);
185
+ }
174
186
J.attribute (" name" , E.Name );
175
187
if (!E.Detail .empty ()) {
176
188
J.attributeObject (" args" , [&] { J.attribute (" detail" , E.Detail ); });
177
189
}
178
190
});
191
+
192
+ if (E.AsyncEvent ) {
193
+ J.object ([&] {
194
+ J.attribute (" pid" , Pid);
195
+ J.attribute (" tid" , int64_t (Tid));
196
+ J.attribute (" ts" , StartUs + DurUs);
197
+ J.attribute (" cat" , E.Name );
198
+ J.attribute (" ph" , " e" );
199
+ J.attribute (" id" , 0 );
200
+ J.attribute (" name" , E.Name );
201
+ });
202
+ }
179
203
};
180
204
for (const TimeTraceProfilerEntry &E : Entries)
181
205
writeEvent (E, this ->Tid );
@@ -269,7 +293,7 @@ struct llvm::TimeTraceProfiler {
269
293
J.objectEnd ();
270
294
}
271
295
272
- SmallVector<TimeTraceProfilerEntry, 16 > Stack;
296
+ SmallVector<std::unique_ptr< TimeTraceProfilerEntry> , 16 > Stack;
273
297
SmallVector<TimeTraceProfilerEntry, 128 > Entries;
274
298
StringMap<CountAndDurationType> CountAndTotalPerName;
275
299
// System clock time when the session was begun.
@@ -341,19 +365,36 @@ Error llvm::timeTraceProfilerWrite(StringRef PreferredFileName,
341
365
return Error::success ();
342
366
}
343
367
344
- void llvm::timeTraceProfilerBegin (StringRef Name, StringRef Detail) {
368
+ TimeTraceProfilerEntry *llvm::timeTraceProfilerBegin (StringRef Name,
369
+ StringRef Detail) {
345
370
if (TimeTraceProfilerInstance != nullptr )
346
- TimeTraceProfilerInstance->begin (std::string (Name),
347
- [&]() { return std::string (Detail); });
371
+ return TimeTraceProfilerInstance->begin (
372
+ std::string (Name), [&]() { return std::string (Detail); }, false );
373
+ return nullptr ;
348
374
}
349
375
350
- void llvm::timeTraceProfilerBegin (StringRef Name,
351
- llvm::function_ref<std::string()> Detail) {
376
+ TimeTraceProfilerEntry *
377
+ llvm::timeTraceProfilerBegin (StringRef Name,
378
+ llvm::function_ref<std::string()> Detail) {
352
379
if (TimeTraceProfilerInstance != nullptr )
353
- TimeTraceProfilerInstance->begin (std::string (Name), Detail);
380
+ return TimeTraceProfilerInstance->begin (std::string (Name), Detail, false );
381
+ return nullptr ;
382
+ }
383
+
384
+ TimeTraceProfilerEntry *llvm::timeTraceAsyncProfilerBegin (StringRef Name,
385
+ StringRef Detail) {
386
+ if (TimeTraceProfilerInstance != nullptr )
387
+ return TimeTraceProfilerInstance->begin (
388
+ std::string (Name), [&]() { return std::string (Detail); }, true );
389
+ return nullptr ;
354
390
}
355
391
356
392
void llvm::timeTraceProfilerEnd () {
357
393
if (TimeTraceProfilerInstance != nullptr )
358
394
TimeTraceProfilerInstance->end ();
359
395
}
396
+
397
+ void llvm::timeTraceProfilerEnd (TimeTraceProfilerEntry *E) {
398
+ if (TimeTraceProfilerInstance != nullptr )
399
+ TimeTraceProfilerInstance->end (*E);
400
+ }
0 commit comments