LLVM: lib/Support/TimeProfiler.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

22#include

23#include

24#include

25#include

26#include

27#include

28#include

29

30using namespace llvm;

31

32namespace {

33

34using std::chrono::duration;

35using std::chrono::duration_cast;

36using std::chrono::microseconds;

37using std::chrono::steady_clock;

39using std::chrono::time_point;

40using std::chrono::time_point_cast;

41

42struct TimeTraceProfilerInstances {

43 std::mutex Lock;

44 std::vector<TimeTraceProfiler *> List;

45};

46

47TimeTraceProfilerInstances &getTimeTraceProfilerInstances() {

48 static TimeTraceProfilerInstances Instances;

49 return Instances;

50}

51

52}

53

54

56

59}

60

61namespace {

62

63using ClockType = steady_clock;

64using TimePointType = time_point;

65using DurationType = duration<ClockType::rep, ClockType::period>;

66using CountAndDurationType = std::pair<size_t, DurationType>;

67using NameAndCountAndDurationType =

68 std::pair<std::string, CountAndDurationType>;

69

70}

71

72

74 const TimePointType Start;

75 TimePointType End;

76 const std::string Name;

78

84 Metadata.Detail = std::move(Dt);

85 }

86

91

92

93

94

96 return (time_point_cast(Start) -

97 time_point_cast(StartTime))

98 .count();

99 }

100

102 return (time_point_cast(End) -

103 time_point_cast(Start))

104 .count();

105 }

106};

107

108

109

110

111

115

120

125};

126

135 }

136

141 "Instant Events don't have begin and end.");

143 ClockType::now(), TimePointType(), std::move(Name), Detail(),

144 EventType));

146 }

147

152 "Instant Events don't have begin and end.");

154 ClockType::now(), TimePointType(), std::move(Name), Metadata(),

155 EventType));

157 }

158

161 return;

162

164 ClockType::now(), TimePointType(), std::move(Name), Detail(),

166 }

167

171 }

172

175 E.End = ClockType::now();

176

177

179

180 const auto *Iter =

181 llvm::find_if(Stack, [&](const std::unique_ptr &Val) {

182 return &Val->Event == &E;

183 });

184 assert(Iter != Stack.end() && "Event not in the Stack");

185

186

189 for (auto &IE : Iter->get()->InstantEvents) {

190 Entries.emplace_back(IE);

191 }

192 }

193

194

195

196

197

198

200 [&](const std::unique_ptr &Val) {

201 return Val->Event.Name == E.Name;

202 })) {

204 CountAndTotal.first++;

205 CountAndTotal.second += Duration;

206 };

207

209 }

210

211

212

214

215 auto &Instances = getTimeTraceProfilerInstances();

216 std::lock_guardstd::mutex Lock(Instances.Lock);

218 "All profiler sections should be ended when calling write");

220 [](const auto &TTP) { return TTP->Stack.empty(); }) &&

221 "All profiler sections should be ended when calling write");

222

227

228

229 auto writeEvent = [&](const auto &E, uint64_t Tid) {

230 auto StartUs = E.getFlameGraphStartUs(StartTime);

231 auto DurUs = E.getFlameGraphDurUs();

232

244 } else {

246 "InstantEvent expected");

248 }

250 if (!E.Metadata.isEmpty()) {

252 if (!E.Metadata.Detail.empty())

253 J.attribute("detail", E.Metadata.Detail);

254 if (!E.Metadata.File.empty())

255 J.attribute("file", E.Metadata.File);

256 if (E.Metadata.Line > 0)

257 J.attribute("line", E.Metadata.Line);

258 });

259 }

260 });

261

266 J.attribute("ts", StartUs + DurUs);

271 });

272 }

273 };

275 writeEvent(E, this->Tid);

278 writeEvent(E, TTP->Tid);

279

280

281

282

285 MaxTid = std::max(MaxTid, TTP->Tid);

286

287

289 auto combineStat = [&](const auto &Stat) {

291 auto Value = Stat.getValue();

292 auto &CountAndTotal = AllCountAndTotalPerName[Key];

293 CountAndTotal.first += Value.first;

294 CountAndTotal.second += Value.second;

295 };

297 combineStat(Stat);

300 combineStat(Stat);

301

302 std::vector SortedTotals;

303 SortedTotals.reserve(AllCountAndTotalPerName.size());

304 for (const auto &Total : AllCountAndTotalPerName)

305 SortedTotals.emplace_back(std::string(Total.getKey()), Total.getValue());

306

307 llvm::sort(SortedTotals, [](const NameAndCountAndDurationType &A,

308 const NameAndCountAndDurationType &B) {

309 return A.second.second > B.second.second;

310 });

311

312

313 uint64_t TotalTid = MaxTid + 1;

314 for (const NameAndCountAndDurationType &Total : SortedTotals) {

315 auto DurUs = duration_cast(Total.second.second).count();

316 auto Count = AllCountAndTotalPerName[Total.first].first;

317

320 J.attribute("tid", int64_t(TotalTid));

326 J.attribute("count", int64_t(Count));

327 J.attribute("avg ms", int64_t(DurUs / Count / 1000));

328 });

329 });

330

331 ++TotalTid;

332 }

333

334 auto writeMetadataEvent = [&](const char *Name, uint64_t Tid,

344 });

345 };

346

347 writeMetadataEvent("process_name", Tid, ProcName);

348 writeMetadataEvent("thread_name", Tid, ThreadName);

350 writeMetadataEvent("thread_name", TTP->Tid, TTP->ThreadName);

351

354

355

356

357

360 .time_since_epoch()

362

364 }

365

369

371

377

378

380

381

382

384};

385

389}

390

393 bool TimeTraceVerbose) {

395 "Profiler should not be initialized");

398 TimeTraceVerbose);

399}

400

401

402

406

407 auto &Instances = getTimeTraceProfilerInstances();

408 std::lock_guardstd::mutex Lock(Instances.Lock);

409 for (auto *TTP : Instances.List)

410 delete TTP;

411 Instances.List.clear();

412}

413

414

415

417 auto &Instances = getTimeTraceProfilerInstances();

418 std::lock_guardstd::mutex Lock(Instances.Lock);

421}

422

425 "Profiler object can't be null");

427}

428

432 "Profiler object can't be null");

433

434 std::string Path = PreferredFileName.str();

435 if (Path.empty()) {

436 Path = FallbackFileName == "-" ? "out" : FallbackFileName.str();

437 Path += ".time-trace";

438 }

439

440 std::error_code EC;

442 if (EC)

444

447}

448

453 std::string(Name), [&]() { return std::string(Detail); },

454 TimeTraceEventType::CompleteEvent);

455 return nullptr;

456}

457

463 TimeTraceEventType::CompleteEvent);

464 return nullptr;

465}

466

472 TimeTraceEventType::CompleteEvent);

473 return nullptr;

474}

475

480 std::string(Name), [&]() { return std::string(Detail); },

481 TimeTraceEventType::AsyncEvent);

482 return nullptr;

483}

484

489}

490

494}

495

499}

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())

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...

reference emplace_back(ArgTypes &&... Args)

iterator erase(const_iterator CI)

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 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 LLVM_LIFETIME_BOUND, 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 timeTraceAddInstantEvent(StringRef Name, llvm::function_ref< std::string()> Detail)

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.

auto find_if(R &&Range, UnaryPredicate P)

Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.

void timeTraceProfilerCleanup()

Cleanup the time trace profiler, if it was initialized.

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.

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

void write(raw_pwrite_stream &OS)

StringMap< CountAndDurationType > CountAndTotalPerName

const unsigned TimeTraceGranularity

void insert(std::string Name, llvm::function_ref< std::string()> Detail)

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)

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)