LLVM 24.0.0git
TimeProfiler.cpp
Go to the documentation of this file.
1//===-- TimeProfiler.cpp - Hierarchical Time Profiler ---------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements hierarchical time profiler.
10//
11//===----------------------------------------------------------------------===//
12
14#include "llvm/ADT/STLExtras.h"
17#include "llvm/ADT/StringMap.h"
19#include "llvm/Support/JSON.h"
20#include "llvm/Support/Path.h"
23#include <algorithm>
24#include <cassert>
25#include <chrono>
26#include <memory>
27#include <mutex>
28#include <string>
29#include <vector>
30
31using namespace llvm;
32
33namespace {
34
35using std::chrono::duration;
36using std::chrono::duration_cast;
37using std::chrono::microseconds;
38using std::chrono::steady_clock;
40using std::chrono::time_point;
41using std::chrono::time_point_cast;
42
43struct TimeTraceProfilerInstances {
44 std::mutex Lock;
45 std::vector<TimeTraceProfiler *> List;
46};
47
48TimeTraceProfilerInstances &getTimeTraceProfilerInstances() {
49 static TimeTraceProfilerInstances Instances;
50 return Instances;
51}
52
53static const char TimeTraceFileExtension[] = ".time-trace.json";
54
55} // anonymous namespace
56
57// Per Thread instance
59
63
64namespace {
65
66using ClockType = steady_clock;
67using TimePointType = time_point<ClockType>;
68using DurationType = duration<ClockType::rep, ClockType::period>;
69using CountAndDurationType = std::pair<size_t, DurationType>;
70using NameAndCountAndDurationType =
71 std::pair<std::string, CountAndDurationType>;
72
73} // anonymous namespace
74
75/// Represents an open or completed time section entry to be captured.
77 const TimePointType Start;
78 TimePointType End;
79 const std::string Name;
81
83 TimeTraceProfilerEntry(TimePointType &&S, TimePointType &&E, std::string &&N,
84 std::string &&Dt, TimeTraceEventType Et)
85 : Start(std::move(S)), End(std::move(E)), Name(std::move(N)), Metadata(),
86 EventType(Et) {
87 Metadata.Detail = std::move(Dt);
88 }
89
90 TimeTraceProfilerEntry(TimePointType &&S, TimePointType &&E, std::string &&N,
92 : Start(std::move(S)), End(std::move(E)), Name(std::move(N)),
93 Metadata(std::move(Mt)), EventType(Et) {}
94
95 // Calculate timings for FlameGraph. Cast time points to microsecond precision
96 // rather than casting duration. This avoids truncation issues causing inner
97 // scopes overruning outer scopes.
98 ClockType::rep getFlameGraphStartUs(TimePointType StartTime) const {
99 return (time_point_cast<microseconds>(Start) -
100 time_point_cast<microseconds>(StartTime))
101 .count();
102 }
103
104 ClockType::rep getFlameGraphDurUs() const {
105 return (time_point_cast<microseconds>(End) -
106 time_point_cast<microseconds>(Start))
107 .count();
108 }
109};
110
111// Represents a currently open (in-progress) time trace entry. InstantEvents
112// that happen during an open event are associated with the duration of this
113// parent event and they are dropped if parent duration is shorter than
114// the granularity.
117 std::vector<TimeTraceProfilerEntry> InstantEvents;
118
119 InProgressEntry(TimePointType S, TimePointType E, std::string N,
120 std::string Dt, TimeTraceEventType Et)
121 : Event(std::move(S), std::move(E), std::move(N), std::move(Dt), Et),
122 InstantEvents() {}
123
124 InProgressEntry(TimePointType S, TimePointType E, std::string N,
126 : Event(std::move(S), std::move(E), std::move(N), std::move(Mt), Et),
127 InstantEvents() {}
128};
129
142
144 begin(std::string Name, llvm::function_ref<std::string()> Detail,
147 "Instant Events don't have begin and end.");
148 Stack.emplace_back(std::make_unique<InProgressEntry>(
149 ClockType::now(), TimePointType(), std::move(Name), Detail(),
150 EventType));
151 return &Stack.back()->Event;
152 }
153
158 "Instant Events don't have begin and end.");
159 Stack.emplace_back(std::make_unique<InProgressEntry>(
160 ClockType::now(), TimePointType(), std::move(Name), Metadata(),
161 EventType));
162 return &Stack.back()->Event;
163 }
164
165 void insert(std::string Name, llvm::function_ref<std::string()> Detail) {
166 if (Stack.empty())
167 return;
168
169 Stack.back()->InstantEvents.emplace_back(TimeTraceProfilerEntry(
170 ClockType::now(), TimePointType(), std::move(Name), Detail(),
172 }
173
174 void end() {
175 assert(!Stack.empty() && "Must call begin() first");
176 end(Stack.back()->Event);
177 }
178
180 assert(!Stack.empty() && "Must call begin() first");
181 E.End = ClockType::now();
182
183 // Calculate duration at full precision for overall counts.
184 DurationType Duration = E.End - E.Start;
185
186 const auto *Iter =
187 llvm::find_if(Stack, [&](const std::unique_ptr<InProgressEntry> &Val) {
188 return &Val->Event == &E;
189 });
190 assert(Iter != Stack.end() && "Event not in the Stack");
191
192 // Only include sections longer or equal to TimeTraceGranularity msec.
193 if (duration_cast<microseconds>(Duration).count() >= TimeTraceGranularity) {
194 Entries.emplace_back(E);
195 for (auto &IE : Iter->get()->InstantEvents) {
196 Entries.emplace_back(IE);
197 }
198 }
199
200 // Track total time taken by each "name", but only the topmost levels of
201 // them; e.g. if there's a template instantiation that instantiates other
202 // templates from within, we only want to add the topmost one. "topmost"
203 // happens to be the ones that don't have any currently open entries above
204 // itself.
206 [&](const std::unique_ptr<InProgressEntry> &Val) {
207 return Val->Event.Name == E.Name;
208 })) {
209 auto &CountAndTotal = CountAndTotalPerName[E.Name];
210 CountAndTotal.first++;
211 CountAndTotal.second += Duration;
212 };
213
214 Stack.erase(Iter);
215 }
216
217 // Write events from this TimeTraceProfilerInstance and
218 // ThreadTimeTraceProfilerInstances.
219 void write(raw_ostream &OS) {
220 // Acquire Mutex as reading ThreadTimeTraceProfilerInstances.
221 auto &Instances = getTimeTraceProfilerInstances();
222 std::lock_guard<std::mutex> Lock(Instances.Lock);
223 assert(Stack.empty() &&
224 "All profiler sections should be ended when calling write");
225 assert(llvm::all_of(Instances.List,
226 [](const auto &TTP) { return TTP->Stack.empty(); }) &&
227 "All profiler sections should be ended when calling write");
228
229 json::OStream J(OS);
230 J.objectBegin();
231 J.attributeBegin("traceEvents");
232 J.arrayBegin();
233
234 // Emit all events for the main flame graph.
235 auto writeEvent = [&](const auto &E, uint64_t Tid) {
236 auto StartUs = E.getFlameGraphStartUs(StartTime);
237 auto DurUs = E.getFlameGraphDurUs();
238
239 J.object([&] {
240 J.attribute("pid", Pid);
241 J.attribute("tid", int64_t(Tid));
242 J.attribute("ts", StartUs);
243 if (E.EventType == TimeTraceEventType::AsyncEvent) {
244 J.attribute("cat", E.Name);
245 J.attribute("ph", "b");
246 J.attribute("id", 0);
247 } else if (E.EventType == TimeTraceEventType::CompleteEvent) {
248 J.attribute("ph", "X");
249 J.attribute("dur", DurUs);
250 } else { // instant event
252 "InstantEvent expected");
253 J.attribute("ph", "i");
254 }
255 J.attribute("name", E.Name);
256 if (!E.Metadata.isEmpty()) {
257 J.attributeObject("args", [&] {
258 if (!E.Metadata.Detail.empty())
259 J.attribute("detail", E.Metadata.Detail);
260 if (!E.Metadata.File.empty())
261 J.attribute("file", E.Metadata.File);
262 if (E.Metadata.Line > 0)
263 J.attribute("line", E.Metadata.Line);
264 });
265 }
266 });
267
268 if (E.EventType == TimeTraceEventType::AsyncEvent) {
269 J.object([&] {
270 J.attribute("pid", Pid);
271 J.attribute("tid", int64_t(Tid));
272 J.attribute("ts", StartUs + DurUs);
273 J.attribute("cat", E.Name);
274 J.attribute("ph", "e");
275 J.attribute("id", 0);
276 J.attribute("name", E.Name);
277 });
278 }
279 };
280 for (const TimeTraceProfilerEntry &E : Entries)
281 writeEvent(E, this->Tid);
282 for (const TimeTraceProfiler *TTP : Instances.List)
283 for (const TimeTraceProfilerEntry &E : TTP->Entries)
284 writeEvent(E, TTP->Tid);
285
286 // Emit totals by section name as additional "thread" events, sorted from
287 // longest one.
288 // Find highest used thread id.
289 uint64_t MaxTid = this->Tid;
290 for (const TimeTraceProfiler *TTP : Instances.List)
291 MaxTid = std::max(MaxTid, TTP->Tid);
292
293 // Combine all CountAndTotalPerName from threads into one.
294 StringMap<CountAndDurationType> AllCountAndTotalPerName;
295 auto combineStat = [&](const auto &Stat) {
296 StringRef Key = Stat.getKey();
297 auto Value = Stat.getValue();
298 auto &CountAndTotal = AllCountAndTotalPerName[Key];
299 CountAndTotal.first += Value.first;
300 CountAndTotal.second += Value.second;
301 };
302 for (const auto &Stat : CountAndTotalPerName)
303 combineStat(Stat);
304 for (const TimeTraceProfiler *TTP : Instances.List)
305 for (const auto &Stat : TTP->CountAndTotalPerName)
306 combineStat(Stat);
307
308 std::vector<NameAndCountAndDurationType> SortedTotals;
309 SortedTotals.reserve(AllCountAndTotalPerName.size());
310 for (const auto &Total : AllCountAndTotalPerName)
311 SortedTotals.emplace_back(std::string(Total.getKey()), Total.getValue());
312
313 llvm::sort(SortedTotals, [](const NameAndCountAndDurationType &A,
314 const NameAndCountAndDurationType &B) {
315 return A.second.second > B.second.second;
316 });
317
318 // Report totals on separate threads of tracing file.
319 uint64_t TotalTid = MaxTid + 1;
320 for (const NameAndCountAndDurationType &Total : SortedTotals) {
321 auto DurUs = duration_cast<microseconds>(Total.second.second).count();
322 auto Count = AllCountAndTotalPerName[Total.first].first;
323
324 J.object([&] {
325 J.attribute("pid", Pid);
326 J.attribute("tid", int64_t(TotalTid));
327 J.attribute("ph", "X");
328 J.attribute("ts", 0);
329 J.attribute("dur", DurUs);
330 J.attribute("name", "Total " + Total.first);
331 J.attributeObject("args", [&] {
332 J.attribute("count", int64_t(Count));
333 J.attribute("avg ms", int64_t(DurUs / Count / 1000));
334 });
335 });
336
337 ++TotalTid;
338 }
339
340 auto writeMetadataEvent = [&](const char *Name, uint64_t Tid,
341 StringRef arg) {
342 J.object([&] {
343 J.attribute("cat", "");
344 J.attribute("pid", Pid);
345 J.attribute("tid", int64_t(Tid));
346 J.attribute("ts", 0);
347 J.attribute("ph", "M");
348 J.attribute("name", Name);
349 J.attributeObject("args", [&] { J.attribute("name", arg); });
350 });
351 };
352
353 writeMetadataEvent("process_name", Tid, ProcName);
354 writeMetadataEvent("thread_name", Tid, ThreadName);
355 for (const TimeTraceProfiler *TTP : Instances.List)
356 writeMetadataEvent("thread_name", TTP->Tid, TTP->ThreadName);
357
358 J.arrayEnd();
359 J.attributeEnd();
360
361 // Emit the absolute time when this TimeProfiler started.
362 // This can be used to combine the profiling data from
363 // multiple processes and preserve actual time intervals.
364 J.attribute("beginningOfTime",
365 time_point_cast<microseconds>(BeginningOfTime)
366 .time_since_epoch()
367 .count());
368
369 J.objectEnd();
370 }
371
375 // System clock time when the session was begun.
376 const time_point<system_clock> BeginningOfTime;
377 // Profiling clock time when the session was begun.
378 const TimePointType StartTime;
379 const std::string ProcName;
382 const uint64_t Tid;
383
384 // Minimum time granularity (in microseconds)
385 const unsigned TimeTraceGranularity;
386
387 // Make time trace capture verbose event details (e.g. source filenames). This
388 // can increase the size of the output by 2-3 times.
390
391 // Compression mode for output.
393};
394
399
406
407void llvm::timeTraceProfilerInitialize(unsigned TimeTraceGranularity,
408 StringRef ProcName,
409 bool TimeTraceVerbose,
410 TimeTraceCompression TimeTraceCompress) {
412 "Profiler should not be initialized");
414 TimeTraceGranularity, llvm::sys::path::filename(ProcName),
415 TimeTraceVerbose, TimeTraceCompress);
416}
417
418// Removes all TimeTraceProfilerInstances.
419// Called from main thread.
423
424 auto &Instances = getTimeTraceProfilerInstances();
425 std::lock_guard<std::mutex> Lock(Instances.Lock);
426 for (auto *TTP : Instances.List)
427 delete TTP;
428 Instances.List.clear();
429}
430
431// Finish TimeTraceProfilerInstance on a worker thread.
432// This doesn't remove the instance, just moves the pointer to global vector.
434 auto &Instances = getTimeTraceProfilerInstances();
435 std::lock_guard<std::mutex> Lock(Instances.Lock);
436 Instances.List.push_back(TimeTraceProfilerInstance);
438}
439
442 "Profiler object can't be null");
443 TimeTraceCompression CompressType =
444 TimeTraceProfilerInstance->TimeTraceCompress;
445 if (CompressType != TimeTraceCompression::Zstd) {
446 TimeTraceProfilerInstance->write(OS);
447 return;
448 }
449
451 if (const char *Reason = compression::getReasonIfUnsupported(F))
452 report_fatal_error(Reason);
453
454 SmallVector<char, 0> Uncompressed;
455 {
456 raw_svector_ostream UncompressedOS(Uncompressed);
457 TimeTraceProfilerInstance->write(UncompressedOS);
458 }
459 SmallVector<uint8_t, 0> Compressed;
462 ArrayRef(reinterpret_cast<const uint8_t *>(Uncompressed.data()),
463 Uncompressed.size()),
464 Compressed);
465 OS.write(reinterpret_cast<const char *>(Compressed.data()),
466 Compressed.size());
467}
468
470 StringRef FallbackFileName) {
472 "Profiler object can't be null");
473
474 TimeTraceCompression CompressType =
475 TimeTraceProfilerInstance->TimeTraceCompress;
476 std::string Path = PreferredFileName.str();
477 if (Path.empty()) {
478 Path = FallbackFileName == "-" ? "out" : FallbackFileName.str();
479 Path += TimeTraceFileExtension;
480 if (CompressType == TimeTraceCompression::Zstd)
481 Path += ".zst";
482 } else if (CompressType == TimeTraceCompression::Infer) {
483 CompressType = inferTimeTraceCompressionFromPath(Path);
484 }
485
486 if (CompressType == TimeTraceCompression::Zstd) {
487 if (const char *Reason =
490 }
491
492 std::error_code EC;
493 sys::fs::OpenFlags Flags = CompressType == TimeTraceCompression::Zstd
496 raw_fd_ostream OS(Path, EC, Flags);
497 if (EC)
498 return createStringError(EC, "Could not open " + Path);
499
500 TimeTraceCompression SavedCompress =
501 TimeTraceProfilerInstance->TimeTraceCompress;
502 TimeTraceProfilerInstance->TimeTraceCompress = CompressType;
504 TimeTraceProfilerInstance->TimeTraceCompress = SavedCompress;
505 return Error::success();
506}
507
509 StringRef Detail) {
510 if (TimeTraceProfilerInstance != nullptr)
511 return TimeTraceProfilerInstance->begin(
512 std::string(Name), [&]() { return std::string(Detail); },
514 return nullptr;
515}
516
519 llvm::function_ref<std::string()> Detail) {
520 if (TimeTraceProfilerInstance != nullptr)
521 return TimeTraceProfilerInstance->begin(std::string(Name), Detail,
523 return nullptr;
524}
525
534
536 StringRef Detail) {
537 if (TimeTraceProfilerInstance != nullptr)
538 return TimeTraceProfilerInstance->begin(
539 std::string(Name), [&]() { return std::string(Detail); },
541 return nullptr;
542}
543
545 llvm::function_ref<std::string()> Detail) {
546 if (TimeTraceProfilerInstance != nullptr)
547 TimeTraceProfilerInstance->insert(std::string(Name), Detail);
548}
549
554
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the StringMap class.
static sys::TimePoint< std::chrono::seconds > now(bool Deterministic)
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_THREAD_LOCAL
\macro LLVM_THREAD_LOCAL A thread-local storage specifier which can be used with globals,...
Definition Compiler.h:723
dxil translate DXIL Translate Metadata
This file supports working with JSON data.
#define F(x, y, z)
Definition MD5.cpp:54
Provides a library for accessing information about this process and other processes on the operating ...
This file contains some templates that are useful if you are working with the STL at all.
This file defines the SmallVector class.
static LLVM_THREAD_LOCAL TimeTraceProfiler * TimeTraceProfilerInstance
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
static ErrorSuccess success()
Create a success value.
Definition Error.h:336
Root of the metadata hierarchy.
Definition Metadata.h:64
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:26
pointer data()
Return a pointer to the vector's buffer, even if empty().
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
unsigned size() const
Definition StringMap.h:104
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
Definition StringMap.h:129
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
std::string str() const
Get the contents as an std::string.
Definition StringRef.h:222
bool equals_insensitive(StringRef RHS) const
Check for string equality, ignoring case.
Definition StringRef.h:170
LLVM Value Representation.
Definition Value.h:75
An efficient, type-erasing, non-owning reference to a callable.
json::OStream allows writing well-formed JSON without materializing all structures as json::Value ahe...
Definition JSON.h:983
void object(Block Contents)
Emit an object whose elements are emitted in the provided Block.
Definition JSON.h:1013
void attributeObject(llvm::StringRef Key, Block Contents)
Emit an attribute whose value is an object with attributes from the Block.
Definition JSON.h:1046
LLVM_ABI void attributeBegin(llvm::StringRef Key)
Definition JSON.cpp:883
void attribute(llvm::StringRef Key, const Value &Contents)
Emit an attribute whose value is self-contained (number, vector<int> etc).
Definition JSON.h:1038
LLVM_ABI void arrayBegin()
Definition JSON.cpp:845
LLVM_ABI void objectBegin()
Definition JSON.cpp:864
LLVM_ABI void arrayEnd()
Definition JSON.cpp:853
LLVM_ABI void attributeEnd()
Definition JSON.cpp:903
LLVM_ABI void objectEnd()
Definition JSON.cpp:872
A raw_ostream that writes to a file descriptor.
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
raw_ostream & write(unsigned char C)
An abstract base class for streams implementations that also support a pwrite operation.
A raw_ostream that writes to an SmallVector or SmallString.
A collection of legacy interfaces for querying information about the current executing process.
Definition Process.h:44
LLVM_ABI const char * getReasonIfUnsupported(Format F)
LLVM_ABI void compress(Params P, ArrayRef< uint8_t > Input, SmallVectorImpl< uint8_t > &Output)
@ OF_TextWithCRLF
The file should be opened in text mode and use a carriage linefeed '\r '.
Definition FileSystem.h:802
LLVM_ABI StringRef filename(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get filename.
Definition Path.cpp:594
LLVM_ABI StringRef extension(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get extension.
Definition Path.cpp:607
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition STLExtras.h:316
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1755
LLVM_ABI std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Definition Error.cpp:94
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition Error.h:1321
LLVM_ABI TimeTraceProfiler * getTimeTraceProfilerInstance()
LLVM_ABI void timeTraceProfilerInitialize(unsigned TimeTraceGranularity, StringRef ProcName, bool TimeTraceVerbose=false, TimeTraceCompression TimeTraceCompress=TimeTraceCompression::Infer)
Initialize the time trace profiler.
auto reverse(ContainerTy &&C)
Definition STLExtras.h:408
LLVM_ABI void timeTraceProfilerFinishThread()
Finish a time trace profiler running on a worker thread.
void sort(IteratorTy Start, IteratorTy End)
Definition STLExtras.h:1652
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1769
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
TimeTraceCompression
Compression mode for time trace output.
LLVM_ABI void timeTraceProfilerEnd()
Manually end the last time section.
LLVM_ABI void timeTraceAddInstantEvent(StringRef Name, llvm::function_ref< std::string()> Detail)
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
LLVM_ABI TimeTraceCompression inferTimeTraceCompressionFromPath(StringRef Path)
Infer the time trace compression format from Path based on its file extension (.zst/....
LLVM_ABI void get_thread_name(SmallVectorImpl< char > &Name)
Get the name of the current thread.
Definition Threading.cpp:39
LLVM_ABI TimeTraceProfilerEntry * timeTraceAsyncProfilerBegin(StringRef Name, StringRef Detail)
Manually begin a time section, with the given Name and Detail.
LLVM_ABI bool isTimeTraceVerbose()
LLVM_ABI uint64_t get_threadid()
Return the current thread id, as used in various OS system calls.
Definition Threading.cpp:33
TimeTraceEventType
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
Definition InstrProf.h:145
auto count(R &&Range, const E &Element)
Wrapper function around std::count to count the number of times an element Element occurs in the give...
Definition STLExtras.h:2028
ArrayRef(const T &OneElt) -> ArrayRef< T >
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1933
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1788
LLVM_ABI void timeTraceProfilerCleanup()
Cleanup the time trace profiler, if it was initialized.
LLVM_ABI void timeTraceProfilerWrite(raw_pwrite_stream &OS)
Write profiling data to output stream.
LLVM_ABI TimeTraceProfilerEntry * timeTraceProfilerBegin(StringRef Name, StringRef Detail)
Manually begin a time section, with the given Name and Detail.
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:878
#define N
std::vector< TimeTraceProfilerEntry > InstantEvents
InProgressEntry(TimePointType S, TimePointType E, std::string N, TimeTraceMetadata Mt, TimeTraceEventType Et)
TimeTraceProfilerEntry Event
InProgressEntry(TimePointType S, TimePointType E, std::string N, std::string Dt, TimeTraceEventType Et)
Represents an open or completed time section entry to be captured.
const TimePointType Start
TimeTraceProfilerEntry(TimePointType &&S, TimePointType &&E, std::string &&N, std::string &&Dt, TimeTraceEventType Et)
ClockType::rep getFlameGraphDurUs() const
TimeTraceProfilerEntry(TimePointType &&S, TimePointType &&E, std::string &&N, TimeTraceMetadata &&Mt, TimeTraceEventType Et)
const TimeTraceEventType EventType
ClockType::rep getFlameGraphStartUs(TimePointType StartTime) const
const sys::Process::Pid Pid
StringMap< CountAndDurationType > CountAndTotalPerName
const unsigned TimeTraceGranularity
TimeTraceCompression TimeTraceCompress
void insert(std::string Name, llvm::function_ref< std::string()> Detail)
void write(raw_ostream &OS)
TimeTraceProfilerEntry * begin(std::string Name, llvm::function_ref< TimeTraceMetadata()> Metadata, TimeTraceEventType EventType=TimeTraceEventType::CompleteEvent)
const time_point< system_clock > BeginningOfTime
SmallVector< std::unique_ptr< InProgressEntry >, 16 > Stack
TimeTraceProfiler(unsigned TimeTraceGranularity=0, StringRef ProcName="", bool TimeTraceVerbose=false, TimeTraceCompression TimeTraceCompress=TimeTraceCompression::Infer)
SmallString< 0 > ThreadName
const std::string ProcName
TimeTraceProfilerEntry * begin(std::string Name, llvm::function_ref< std::string()> Detail, TimeTraceEventType EventType=TimeTraceEventType::CompleteEvent)
SmallVector< TimeTraceProfilerEntry, 128 > Entries
const TimePointType StartTime
void end(TimeTraceProfilerEntry &E)