MimIR
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
profile.h
Go to the documentation of this file.
1#pragma once
2
3#include <chrono>
4#include <cstdint>
5
6#include <limits>
7#include <ostream>
8#include <string>
9#include <string_view>
10#include <utility>
11
12#include "mim/util/vector.h"
13
14namespace mim {
15
16/// Records wall-clock timings for (possibly nested) Phase runs and reports them in various formats.
17/// Phase%es nest: a PhaseMan runs sub-Phase%es, so each run is recorded as a Profiler::Span that remembers its parent.
18/// From these Span%s the Profiler can derive
19/// - a flat Profiler::summary aggregated by Phase name,
20/// - a hierarchical Profiler::tree that shows the runtimes in context, and
21/// - a [Chrome Trace Event](https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU)
22/// JSON dump (Profiler::chrome_trace) that can be loaded into `chrome://tracing`, Perfetto, or speedscope.
23/// @see Profiler::start, Profiler::stop
24class Profiler {
25public:
26 using Clock = std::chrono::steady_clock;
27 using Duration = Clock::duration;
28
29 static constexpr size_t No_Parent = std::numeric_limits<size_t>::max();
30
31 /// A single Phase run.
32 struct Span {
33 std::string name;
34 Clock::time_point start;
35 Clock::time_point stop;
36 size_t depth; ///< Nesting level; a root Phase has depth 0.
37 size_t parent; ///< Index of the enclosing Span in Profiler::spans, or Profiler::No_Parent for a root.
38 Vector<std::pair<std::string, uint64_t>> counters; ///< Custom counters reported by the Phase (insertion order).
39
40 Duration elapsed() const { return stop - start; }
41 };
42
43 /// @name Getters
44 ///@{
45 bool empty() const { return spans_.empty(); }
46 const auto& spans() const { return spans_; }
47 ///@}
48
49 /// @name Recording
50 /// Bracket a Phase run with Profiler::start / Profiler::stop; the calls must nest like a stack.
51 ///@{
52 /// Marks the start of a Phase run named @p name.
53 void start(std::string_view name) {
54 auto parent = stack_.empty() ? No_Parent : stack_.back();
55 stack_.emplace_back(spans_.size());
56 spans_.emplace_back(std::string(name), Clock::now(), Clock::time_point{}, stack_.size() - 1, parent);
57 }
58
59 /// Marks the end of the most recently started Phase run.
60 void stop() {
61 auto id = stack_.back();
62 stack_.pop_back();
63 spans_[id].stop = Clock::now();
64 }
65
66 /// Adds @p n to counter @p key of the currently running Span; no-op if no Span is running or @p n is `0`.
67 void count(std::string_view key, uint64_t n = 1) {
68 if (stack_.empty() || n == 0) return;
69 auto& counters = spans_[stack_.back()].counters;
70 for (auto& [k, v] : counters) {
71 if (k == key) {
72 v += n;
73 return;
74 }
75 }
76 counters.emplace_back(std::string(key), n);
77 }
78 ///@}
79
80 /// @name Reporting
81 ///@{
82 /// Prints a flat table aggregated by Phase name, sorted by total time, descending.
83 void summary(std::ostream&) const;
84 /// Prints the Span%s as an indented tree, preserving the order in which Phase%es ran.
85 void tree(std::ostream&) const;
86 /// Dumps all Span%s as Chrome Trace Event Format JSON.
87 void chrome_trace(std::ostream&) const;
88 ///@}
89
90private:
91 /// Per-Span time spent in *direct* children; `self = elapsed - children`.
92 Vector<Duration> children_durations() const;
93
94 Vector<size_t> stack_;
95 Vector<Span> spans_;
96};
97
98} // namespace mim
Records wall-clock timings for (possibly nested) Phase runs and reports them in various formats.
Definition profile.h:24
std::chrono::steady_clock Clock
Definition profile.h:26
void stop()
Marks the end of the most recently started Phase run.
Definition profile.h:60
const auto & spans() const
Definition profile.h:46
void chrome_trace(std::ostream &) const
Dumps all Spans as Chrome Trace Event Format JSON.
Definition profile.cpp:116
void start(std::string_view name)
Definition profile.h:53
void count(std::string_view key, uint64_t n=1)
Adds n to counter key of the currently running Span; no-op if no Span is running or n is 0.
Definition profile.h:67
void summary(std::ostream &) const
Definition profile.cpp:47
static constexpr size_t No_Parent
Definition profile.h:29
bool empty() const
Definition profile.h:45
void tree(std::ostream &) const
Prints the Spans as an indented tree, preserving the order in which Phasees ran.
Definition profile.cpp:94
Clock::duration Duration
Definition profile.h:27
This is a thin wrapper for absl::InlinedVector<T, N, A> which is a drop-in replacement for std::vecto...
Definition vector.h:18
Definition ast.h:14
A single Phase run.
Definition profile.h:32
size_t depth
Nesting level; a root Phase has depth 0.
Definition profile.h:36
Clock::time_point start
Definition profile.h:34
size_t parent
Index of the enclosing Span in Profiler::spans, or Profiler::No_Parent for a root.
Definition profile.h:37
Duration elapsed() const
Definition profile.h:40
Clock::time_point stop
Definition profile.h:35
std::string name
Definition profile.h:33
Vector< std::pair< std::string, uint64_t > > counters
Custom counters reported by the Phase (insertion order).
Definition profile.h:38