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;
43struct TimeTraceProfilerInstances {
45 std::vector<TimeTraceProfiler *> List;
48TimeTraceProfilerInstances &getTimeTraceProfilerInstances() {
49 static TimeTraceProfilerInstances Instances;
53static const char TimeTraceFileExtension[] =
".time-trace.json";
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>;
99 return (time_point_cast<microseconds>(
Start) -
100 time_point_cast<microseconds>(StartTime))
105 return (time_point_cast<microseconds>(
End) -
106 time_point_cast<microseconds>(
Start))
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(),
151 return &
Stack.back()->Event;
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(),
162 return &
Stack.back()->Event;
170 ClockType::now(), TimePointType(), std::move(Name), Detail(),
175 assert(!
Stack.empty() &&
"Must call begin() first");
180 assert(!
Stack.empty() &&
"Must call begin() first");
181 E.End = ClockType::now();
184 DurationType
Duration = E.End - E.Start;
188 return &Val->Event == &E;
190 assert(Iter !=
Stack.end() &&
"Event not in the Stack");
195 for (
auto &IE : Iter->get()->InstantEvents) {
206 [&](
const std::unique_ptr<InProgressEntry> &Val) {
207 return Val->Event.Name == E.Name;
210 CountAndTotal.first++;
221 auto &Instances = getTimeTraceProfilerInstances();
222 std::lock_guard<std::mutex> Lock(Instances.Lock);
224 "All profiler sections should be ended when calling write");
226 [](
const auto &TTP) { return TTP->Stack.empty(); }) &&
227 "All profiler sections should be ended when calling write");
235 auto writeEvent = [&](
const auto &E, uint64_t
Tid) {
236 auto StartUs = E.getFlameGraphStartUs(
StartTime);
237 auto DurUs = E.getFlameGraphDurUs();
252 "InstantEvent expected");
256 if (!E.Metadata.isEmpty()) {
258 if (!E.Metadata.Detail.empty())
259 J.
attribute(
"detail", E.Metadata.Detail);
260 if (!E.Metadata.File.empty())
262 if (E.Metadata.Line > 0)
281 writeEvent(E, this->
Tid);
284 writeEvent(E, TTP->
Tid);
289 uint64_t MaxTid = this->
Tid;
291 MaxTid = std::max(MaxTid, TTP->
Tid);
295 auto combineStat = [&](
const auto &Stat) {
297 auto Value = Stat.getValue();
298 auto &CountAndTotal = AllCountAndTotalPerName[
Key];
299 CountAndTotal.first +=
Value.first;
300 CountAndTotal.second +=
Value.second;
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());
313 llvm::sort(SortedTotals, [](
const NameAndCountAndDurationType &
A,
314 const NameAndCountAndDurationType &
B) {
315 return A.second.second >
B.second.second;
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;
340 auto writeMetadataEvent = [&](
const char *Name, uint64_t
Tid,
356 writeMetadataEvent(
"thread_name", TTP->
Tid, TTP->
ThreadName);
409 bool TimeTraceVerbose,
412 "Profiler should not be initialized");
415 TimeTraceVerbose, TimeTraceCompress);
424 auto &Instances = getTimeTraceProfilerInstances();
425 std::lock_guard<std::mutex> Lock(Instances.Lock);
426 for (
auto *TTP : Instances.List)
428 Instances.List.clear();
434 auto &Instances = getTimeTraceProfilerInstances();
435 std::lock_guard<std::mutex> Lock(Instances.Lock);
442 "Profiler object can't be null");
463 Uncompressed.
size()),
465 OS.
write(
reinterpret_cast<const char *
>(Compressed.
data()),
472 "Profiler object can't be null");
476 std::string Path = PreferredFileName.
str();
478 Path = FallbackFileName ==
"-" ?
"out" : FallbackFileName.
str();
479 Path += TimeTraceFileExtension;
487 if (
const char *Reason =
512 std::string(Name), [&]() {
return std::string(Detail); },
539 std::string(Name), [&]() {
return std::string(Detail); },
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,...
This file supports working with JSON data.
Provides a library for accessing information about this process and other processes on the operating ...
This file defines the SmallVector class.
static LLVM_THREAD_LOCAL TimeTraceProfiler * TimeTraceProfilerInstance
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
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.
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
Represent a constant reference to a string, i.e.
std::string str() const
Get the contents as an std::string.
bool equals_insensitive(StringRef RHS) const
Check for string equality, ignoring case.
LLVM Value Representation.
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...
void object(Block Contents)
Emit an object whose elements are emitted in the provided Block.
void attributeObject(llvm::StringRef Key, Block Contents)
Emit an attribute whose value is an object with attributes from the Block.
LLVM_ABI void attributeBegin(llvm::StringRef Key)
void attribute(llvm::StringRef Key, const Value &Contents)
Emit an attribute whose value is self-contained (number, vector<int> etc).
LLVM_ABI void arrayBegin()
LLVM_ABI void objectBegin()
LLVM_ABI void attributeEnd()
LLVM_ABI void objectEnd()
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.
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.
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 '.
LLVM_ABI StringRef filename(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get filename.
LLVM_ABI StringRef extension(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get extension.
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.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
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)
LLVM_ABI void timeTraceProfilerFinishThread()
Finish a time trace profiler running on a worker thread.
void sort(IteratorTy Start, IteratorTy End)
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
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.
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.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
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...
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.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
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.
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
TimeTraceMetadata Metadata
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 bool TimeTraceVerbose
const TimePointType StartTime
void end(TimeTraceProfilerEntry &E)