Flutter Engine
flutter::Stopwatch Class Reference

#include <instrumentation.h>

Public Member Functions

 Stopwatch (fml::Milliseconds frame_budget=fml::kDefaultFrameBudget)
 
 ~Stopwatch ()
 
const fml::TimeDeltaLastLap () const
 
fml::TimeDelta CurrentLap () const
 
fml::TimeDelta MaxDelta () const
 
fml::TimeDelta AverageDelta () const
 
void InitVisualizeSurface (const SkRect &rect) const
 
void Visualize (SkCanvas *canvas, const SkRect &rect) const
 
void Start ()
 
void Stop ()
 
void SetLapTime (const fml::TimeDelta &delta)
 

Detailed Description

Definition at line 17 of file instrumentation.h.

Constructor & Destructor Documentation

◆ Stopwatch()

flutter::Stopwatch::Stopwatch ( fml::Milliseconds  frame_budget = fml::kDefaultFrameBudget)

Definition at line 18 of file instrumentation.cc.

References fml::TimeDelta::Zero(), and ~Stopwatch().

19  : start_(fml::TimePoint::Now()), current_sample_(0) {
20  const fml::TimeDelta delta = fml::TimeDelta::Zero();
21  laps_.resize(kMaxSamples, delta);
22  cache_dirty_ = true;
23  prev_drawn_sample_index_ = 0;
24  frame_budget_ = frame_budget;
25 }
static constexpr TimeDelta Zero()
Definition: time_delta.h:33
static const size_t kMaxSamples
static TimePoint Now()
Definition: time_point.cc:26

◆ ~Stopwatch()

flutter::Stopwatch::~Stopwatch ( )
default

Referenced by Stopwatch().

Member Function Documentation

◆ AverageDelta()

fml::TimeDelta flutter::Stopwatch::AverageDelta ( ) const

Definition at line 70 of file instrumentation.cc.

References flutter::kMaxSamples.

Referenced by CurrentLap(), and flutter::PerformanceOverlayLayer::MakeStatisticsText().

70  {
71  fml::TimeDelta sum; // default to 0
72  for (size_t i = 0; i < kMaxSamples; i++) {
73  sum = sum + laps_[i];
74  }
75  return sum / kMaxSamples;
76 }
static const size_t kMaxSamples

◆ CurrentLap()

fml::TimeDelta flutter::Stopwatch::CurrentLap ( ) const
inline

Definition at line 25 of file instrumentation.h.

References AverageDelta(), InitVisualizeSurface(), MaxDelta(), fml::TimePoint::Now(), SetLapTime(), Start(), Stop(), and Visualize().

25 { return fml::TimePoint::Now() - start_; }
static TimePoint Now()
Definition: time_point.cc:26

◆ InitVisualizeSurface()

void flutter::Stopwatch::InitVisualizeSurface ( const SkRect &  rect) const

Definition at line 80 of file instrumentation.cc.

References height, flutter::kMaxSamples, flutter::path, and width.

Referenced by CurrentLap(), and Visualize().

80  {
81  if (!cache_dirty_) {
82  return;
83  }
84  cache_dirty_ = false;
85 
86  // TODO(garyq): Use a GPU surface instead of a CPU surface.
87  visualize_cache_surface_ =
88  SkSurface::MakeRasterN32Premul(rect.width(), rect.height());
89 
90  SkCanvas* cache_canvas = visualize_cache_surface_->getCanvas();
91 
92  // Establish the graph position.
93  const SkScalar x = 0;
94  const SkScalar y = 0;
95  const SkScalar width = rect.width();
96  const SkScalar height = rect.height();
97 
98  SkPaint paint;
99  paint.setColor(0x99FFFFFF);
100  cache_canvas->drawRect(SkRect::MakeXYWH(x, y, width, height), paint);
101 
102  // Scale the graph to show frame times up to those that are 3 times the frame
103  // time.
104  const double one_frame_ms = frame_budget_.count();
105  const double max_interval = one_frame_ms * 3.0;
106  const double max_unit_interval = UnitFrameInterval(max_interval);
107 
108  // Draw the old data to initially populate the graph.
109  // Prepare a path for the data. We start at the height of the last point, so
110  // it looks like we wrap around
111  SkPath path;
112  path.setIsVolatile(true);
113  path.moveTo(x, height);
114  path.lineTo(x, y + height * (1.0 - UnitHeight(laps_[0].ToMillisecondsF(),
115  max_unit_interval)));
116  double unit_x;
117  double unit_next_x = 0.0;
118  for (size_t i = 0; i < kMaxSamples; i += 1) {
119  unit_x = unit_next_x;
120  unit_next_x = (static_cast<double>(i + 1) / kMaxSamples);
121  const double sample_y =
122  y + height * (1.0 - UnitHeight(laps_[i].ToMillisecondsF(),
123  max_unit_interval));
124  path.lineTo(x + width * unit_x, sample_y);
125  path.lineTo(x + width * unit_next_x, sample_y);
126  }
127  path.lineTo(
128  width,
129  y + height * (1.0 - UnitHeight(laps_[kMaxSamples - 1].ToMillisecondsF(),
130  max_unit_interval)));
131  path.lineTo(width, height);
132  path.close();
133 
134  // Draw the graph.
135  paint.setColor(0xAA0000FF);
136  cache_canvas->drawPath(path, paint);
137 }
DEF_SWITCHES_START snapshot asset path
Definition: switches.h:32
static const size_t kMaxSamples
int32_t height
int32_t width

◆ LastLap()

const fml::TimeDelta & flutter::Stopwatch::LastLap ( ) const

Definition at line 43 of file instrumentation.cc.

Referenced by Visualize().

43  {
44  return laps_[(current_sample_ - 1) % kMaxSamples];
45 }
static const size_t kMaxSamples

◆ MaxDelta()

fml::TimeDelta flutter::Stopwatch::MaxDelta ( ) const

Definition at line 60 of file instrumentation.cc.

References flutter::kMaxSamples.

Referenced by CurrentLap(), and flutter::PerformanceOverlayLayer::MakeStatisticsText().

60  {
61  fml::TimeDelta max_delta;
62  for (size_t i = 0; i < kMaxSamples; i++) {
63  if (laps_[i] > max_delta) {
64  max_delta = laps_[i];
65  }
66  }
67  return max_delta;
68 }
static const size_t kMaxSamples

◆ SetLapTime()

void flutter::Stopwatch::SetLapTime ( const fml::TimeDelta delta)

Definition at line 38 of file instrumentation.cc.

Referenced by CurrentLap().

38  {
39  current_sample_ = (current_sample_ + 1) % kMaxSamples;
40  laps_[current_sample_] = delta;
41 }
static const size_t kMaxSamples

◆ Start()

void flutter::Stopwatch::Start ( )

Definition at line 29 of file instrumentation.cc.

References fml::TimePoint::Now().

Referenced by flutter::CompositorContext::CompositorContext(), and CurrentLap().

29  {
30  start_ = fml::TimePoint::Now();
31  current_sample_ = (current_sample_ + 1) % kMaxSamples;
32 }
static const size_t kMaxSamples
static TimePoint Now()
Definition: time_point.cc:26

◆ Stop()

void flutter::Stopwatch::Stop ( )

Definition at line 34 of file instrumentation.cc.

References fml::TimePoint::Now().

Referenced by flutter::CompositorContext::CompositorContext(), and CurrentLap().

34  {
35  laps_[current_sample_] = fml::TimePoint::Now() - start_;
36 }
static TimePoint Now()
Definition: time_point.cc:26

◆ Visualize()

void flutter::Stopwatch::Visualize ( SkCanvas *  canvas,
const SkRect &  rect 
) const

Definition at line 139 of file instrumentation.cc.

References height, InitVisualizeSurface(), flutter::kMaxSamples, LastLap(), and width.

Referenced by CurrentLap().

139  {
140  // Initialize visualize cache if it has not yet been initialized.
141  InitVisualizeSurface(rect);
142 
143  SkCanvas* cache_canvas = visualize_cache_surface_->getCanvas();
144  SkPaint paint;
145 
146  // Establish the graph position.
147  const SkScalar x = 0;
148  const SkScalar y = 0;
149  const SkScalar width = rect.width();
150  const SkScalar height = rect.height();
151 
152  // Scale the graph to show frame times up to those that are 3 times the frame
153  // time.
154  const double one_frame_ms = frame_budget_.count();
155  const double max_interval = one_frame_ms * 3.0;
156  const double max_unit_interval = UnitFrameInterval(max_interval);
157 
158  const double sample_unit_width = (1.0 / kMaxSamples);
159 
160  // Draw vertical replacement bar to erase old/stale pixels.
161  paint.setColor(0x99FFFFFF);
162  paint.setStyle(SkPaint::Style::kFill_Style);
163  paint.setBlendMode(SkBlendMode::kSrc);
164  double sample_x =
165  x + width * (static_cast<double>(prev_drawn_sample_index_) / kMaxSamples);
166  const auto eraser_rect = SkRect::MakeLTRB(
167  sample_x, y, sample_x + width * sample_unit_width, height);
168  cache_canvas->drawRect(eraser_rect, paint);
169 
170  // Draws blue timing bar for new data.
171  paint.setColor(0xAA0000FF);
172  paint.setBlendMode(SkBlendMode::kSrcOver);
173  const auto bar_rect = SkRect::MakeLTRB(
174  sample_x,
175  y + height * (1.0 -
176  UnitHeight(laps_[current_sample_ == 0 ? kMaxSamples - 1
177  : current_sample_ - 1]
178  .ToMillisecondsF(),
179  max_unit_interval)),
180  sample_x + width * sample_unit_width, height);
181  cache_canvas->drawRect(bar_rect, paint);
182 
183  // Draw horizontal frame markers.
184  paint.setStrokeWidth(0); // hairline
185  paint.setStyle(SkPaint::Style::kStroke_Style);
186  paint.setColor(0xCC000000);
187 
188  if (max_interval > one_frame_ms) {
189  // Paint the horizontal markers
190  size_t frame_marker_count =
191  static_cast<size_t>(max_interval / one_frame_ms);
192 
193  // Limit the number of markers displayed. After a certain point, the graph
194  // becomes crowded
195  if (frame_marker_count > kMaxFrameMarkers) {
196  frame_marker_count = 1;
197  }
198 
199  for (size_t frame_index = 0; frame_index < frame_marker_count;
200  frame_index++) {
201  const double frame_height =
202  height * (1.0 - (UnitFrameInterval((frame_index + 1) * one_frame_ms) /
203  max_unit_interval));
204  cache_canvas->drawLine(x, y + frame_height, width, y + frame_height,
205  paint);
206  }
207  }
208 
209  // Paint the vertical marker for the current frame.
210  // We paint it over the current frame, not after it, because when we
211  // paint this we don't yet have all the times for the current frame.
212  paint.setStyle(SkPaint::Style::kFill_Style);
213  paint.setBlendMode(SkBlendMode::kSrcOver);
214  if (UnitFrameInterval(LastLap().ToMillisecondsF()) > 1.0) {
215  // budget exceeded
216  paint.setColor(SK_ColorRED);
217  } else {
218  // within budget
219  paint.setColor(SK_ColorGREEN);
220  }
221  sample_x = x + width * (static_cast<double>(current_sample_) / kMaxSamples);
222  const auto marker_rect = SkRect::MakeLTRB(
223  sample_x, y, sample_x + width * sample_unit_width, height);
224  cache_canvas->drawRect(marker_rect, paint);
225  prev_drawn_sample_index_ = current_sample_;
226 
227  // Draw the cached surface onto the output canvas.
228  paint.reset();
229  visualize_cache_surface_->draw(canvas, rect.x(), rect.y(), &paint);
230 }
static const size_t kMaxSamples
int32_t height
int32_t width
static const size_t kMaxFrameMarkers
const fml::TimeDelta & LastLap() const
void InitVisualizeSurface(const SkRect &rect) const

The documentation for this class was generated from the following files: