33using std::chrono::duration;
34using std::chrono::duration_cast;
35using std::chrono::microseconds;
36using std::chrono::steady_clock;
38using std::chrono::time_point;
39using std::chrono::time_point_cast;
41struct TimeTraceProfilerInstances {
43 std::vector<TimeTraceProfiler *>
List;
46TimeTraceProfilerInstances &getTimeTraceProfilerInstances() {
47 static TimeTraceProfilerInstances Instances;
62using ClockType = steady_clock;
63using TimePointType = time_point<ClockType>;
64using DurationType = duration<ClockType::rep, ClockType::period>;
65using CountAndDurationType = std::pair<size_t, DurationType>;
66using NameAndCountAndDurationType =
67 std::pair<std::string, CountAndDurationType>;
80 std::string &&Dt,
bool Ae)
95 return (time_point_cast<microseconds>(
Start) -
96 time_point_cast<microseconds>(StartTime))
101 return (time_point_cast<microseconds>(
End) -
102 time_point_cast<microseconds>(
Start))
119 bool AsyncEvent =
false) {
120 Stack.emplace_back(std::make_unique<TimeTraceProfilerEntry>(
121 ClockType::now(), TimePointType(), std::move(
Name), Detail(),
123 return Stack.back().get();
128 bool AsyncEvent =
false) {
129 Stack.emplace_back(std::make_unique<TimeTraceProfilerEntry>(
130 ClockType::now(), TimePointType(), std::move(
Name),
Metadata(),
132 return Stack.back().get();
136 assert(!
Stack.empty() &&
"Must call begin() first");
141 assert(!
Stack.empty() &&
"Must call begin() first");
142 E.
End = ClockType::now();
157 [&](
const std::unique_ptr<TimeTraceProfilerEntry> &Val) {
158 return Val->Name == E.
Name;
161 CountAndTotal.first++;
166 [&](
const std::unique_ptr<TimeTraceProfilerEntry> &Val) {
167 return Val.get() == &E;
175 auto &Instances = getTimeTraceProfilerInstances();
176 std::lock_guard<std::mutex> Lock(Instances.Lock);
178 "All profiler sections should be ended when calling write");
180 [](
const auto &TTP) { return TTP->Stack.empty(); }) &&
181 "All profiler sections should be ended when calling write");
189 auto writeEvent = [&](
const auto &E,
uint64_t Tid) {
190 auto StartUs = E.getFlameGraphStartUs(
StartTime);
191 auto DurUs = E.getFlameGraphDurUs();
206 if (!E.Metadata.isEmpty()) {
208 if (!E.Metadata.Detail.empty())
209 J.
attribute(
"detail", E.Metadata.Detail);
210 if (!E.Metadata.File.empty())
212 if (E.Metadata.Line > 0)
231 writeEvent(E, this->
Tid);
234 writeEvent(E, TTP->
Tid);
241 MaxTid = std::max(MaxTid, TTP->
Tid);
245 auto combineStat = [&](
const auto &Stat) {
247 auto Value = Stat.getValue();
248 auto &CountAndTotal = AllCountAndTotalPerName[Key];
249 CountAndTotal.first +=
Value.first;
250 CountAndTotal.second +=
Value.second;
258 std::vector<NameAndCountAndDurationType> SortedTotals;
259 SortedTotals.reserve(AllCountAndTotalPerName.
size());
260 for (
const auto &
Total : AllCountAndTotalPerName)
261 SortedTotals.emplace_back(std::string(
Total.getKey()),
Total.getValue());
263 llvm::sort(SortedTotals, [](
const NameAndCountAndDurationType &
A,
264 const NameAndCountAndDurationType &
B) {
265 return A.second.second >
B.second.second;
270 for (
const NameAndCountAndDurationType &
Total : SortedTotals) {
271 auto DurUs = duration_cast<microseconds>(
Total.second.second).count();
272 auto Count = AllCountAndTotalPerName[
Total.first].first;
282 J.attribute(
"count", int64_t(Count));
283 J.attribute(
"avg ms", int64_t(DurUs / Count / 1000));
306 writeMetadataEvent(
"thread_name", TTP->
Tid, TTP->
ThreadName);
349 bool TimeTraceVerbose) {
351 "Profiler should not be initialized");
363 auto &Instances = getTimeTraceProfilerInstances();
364 std::lock_guard<std::mutex> Lock(Instances.Lock);
365 for (
auto *TTP : Instances.List)
367 Instances.List.clear();
373 auto &Instances = getTimeTraceProfilerInstances();
374 std::lock_guard<std::mutex> Lock(Instances.Lock);
381 "Profiler object can't be null");
388 "Profiler object can't be null");
390 std::string Path = PreferredFileName.
str();
392 Path = FallbackFileName ==
"-" ?
"out" : FallbackFileName.
str();
393 Path +=
".time-trace";
409 std::string(
Name), [&]() {
return std::string(Detail); },
false);
433 std::string(
Name), [&]() {
return std::string(Detail); },
true);
This file defines the StringMap class.
static sys::TimePoint< std::chrono::seconds > now(bool Deterministic)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
#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 ...
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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...
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",...
StringRef - Represent a constant reference to a string, i.e.
std::string str() const
str - Get the contents as an std::string.
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.
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).
A raw_ostream that writes to a file descriptor.
An abstract base class for streams implementations that also support a pwrite operation.
A collection of legacy interfaces for querying information about the current executing process.
@ OF_TextWithCRLF
The file should be opened in text mode and use a carriage linefeed '\r '.
StringRef filename(StringRef path, Style style=Style::native)
Get filename.
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.
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
TimeTraceProfiler * getTimeTraceProfilerInstance()
void timeTraceProfilerInitialize(unsigned TimeTraceGranularity, StringRef ProcName, bool TimeTraceVerbose=false)
Initialize the time trace profiler.
auto reverse(ContainerTy &&C)
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.
void timeTraceProfilerEnd()
Manually end the last time section.
void get_thread_name(SmallVectorImpl< char > &Name)
Get the name of the current thread.
TimeTraceProfilerEntry * timeTraceAsyncProfilerBegin(StringRef Name, StringRef Detail)
Manually begin a time section, with the given Name and Detail.
bool isTimeTraceVerbose()
uint64_t get_threadid()
Return the current thread id, as used in various OS system calls.
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...
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
void timeTraceProfilerCleanup()
Cleanup the time trace profiler, if it was initialized.
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
void timeTraceProfilerWrite(raw_pwrite_stream &OS)
Write profiling data to output stream.
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.
Represents an open or completed time section entry to be captured.
const TimePointType Start
ClockType::rep getFlameGraphDurUs() const
TimeTraceProfilerEntry(TimePointType &&S, TimePointType &&E, std::string &&N, std::string &&Dt, bool Ae)
ClockType::rep getFlameGraphStartUs(TimePointType StartTime) const
TimeTraceMetadata Metadata
TimeTraceProfilerEntry(TimePointType &&S, TimePointType &&E, std::string &&N, TimeTraceMetadata &&Mt, bool Ae)
const sys::Process::Pid Pid
void write(raw_pwrite_stream &OS)
StringMap< CountAndDurationType > CountAndTotalPerName
TimeTraceProfilerEntry * begin(std::string Name, llvm::function_ref< TimeTraceMetadata()> Metadata, bool AsyncEvent=false)
const unsigned TimeTraceGranularity
TimeTraceProfilerEntry * begin(std::string Name, llvm::function_ref< std::string()> Detail, bool AsyncEvent=false)
const time_point< system_clock > BeginningOfTime
TimeTraceProfiler(unsigned TimeTraceGranularity=0, StringRef ProcName="", bool TimeTraceVerbose=false)
SmallVector< std::unique_ptr< TimeTraceProfilerEntry >, 16 > Stack
SmallString< 0 > ThreadName
const std::string ProcName
SmallVector< TimeTraceProfilerEntry, 128 > Entries
const bool TimeTraceVerbose
const TimePointType StartTime
void end(TimeTraceProfilerEntry &E)