Skip to content

Commit

Permalink
Performance Overlay fixes
Browse files Browse the repository at this point in the history
- fix dartdocs for addPerformanceOverlay
- make PerformanceOverlayLayer honour its x, y, and height.
- fix the y axis of PerformanceOverlayLayer to only show 3x16ms, since
  if it's more than 16ms it really doesn't matter what it is.
- make the label on the PerformanceOverlayLayer show the worst time on
  record not the instantaneous time.
- pin the fps to a maximum of 60Hz
  • Loading branch information
Hixie committed Mar 18, 2016
1 parent 99f1529 commit 389bc4b
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 62 deletions.
85 changes: 46 additions & 39 deletions flow/instrumentation.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ namespace instrumentation {

static const size_t kMaxSamples = 120;
static const size_t kMaxFrameMarkers = 8;
static const double kOneFrameMS = 1e3 / 60.0;

Stopwatch::Stopwatch() : _start(base::TimeTicks::Now()), _current_sample(0) {
const base::TimeDelta delta;
Expand Down Expand Up @@ -42,6 +41,13 @@ static inline constexpr double UnitFrameInterval(double frameTimeMS) {
return frameTimeMS * 60.0 * 1e-3;
}

static inline double UnitHeight(double frameTimeMS, double maxUnitInterval) {
double unitHeight = UnitFrameInterval(frameTimeMS) / maxUnitInterval;
if (unitHeight > 1.0)
unitHeight = 1.0;
return unitHeight;
}

base::TimeDelta Stopwatch::maxDelta() const {
base::TimeDelta maxDelta;
for (size_t i = 0; i < kMaxSamples; i++) {
Expand All @@ -55,52 +61,53 @@ base::TimeDelta Stopwatch::maxDelta() const {
void Stopwatch::visualize(SkCanvas& canvas, const SkRect& rect) const {
SkPaint paint;

// Paint the background
paint.setColor(0xAAFFFFFF);
// Paint the background.
paint.setColor(0x99FFFFFF);
canvas.drawRect(rect, paint);

// Paint the graph
SkPath path;
// Establish the graph position.
const SkScalar x = rect.x();
const SkScalar y = rect.y();
const SkScalar width = rect.width();
const SkScalar height = rect.height();
const SkScalar bottom = y + height;
const SkScalar right = x + width;

// Find the max delta. We use this to scale the graph

double maxInterval = maxDelta().InMillisecondsF();

if (maxInterval < kOneFrameMS) {
maxInterval = kOneFrameMS;
} else {
maxInterval =
kOneFrameMS * (static_cast<size_t>(maxInterval / kOneFrameMS) + 1);
}

// Scale the graph to show frame times up to those that are 4 times the frame time.
const double maxInterval = kOneFrameMS * 3.0;
const double maxUnitInterval = UnitFrameInterval(maxInterval);

// Draw the path
double unitHeight =
UnitFrameInterval(_laps[0].InMillisecondsF()) / maxUnitInterval;

path.moveTo(0, height);
path.lineTo(0, height * (1.0 - unitHeight));

for (size_t i = 0; i < kMaxSamples; i++) {
double unitWidth = (static_cast<double>(i + 1) / kMaxSamples);
unitHeight =
UnitFrameInterval(_laps[i].InMillisecondsF()) / maxUnitInterval;
path.lineTo(width * unitWidth, height * (1.0 - unitHeight));
// Prepare a path for the data.
// we start at the height of the last point, so it looks like we wrap around
SkPath path;
const double sampleMarginUnitWidth = (1.0 / kMaxSamples) / 6.0;
const double sampleMarginWidth = width * sampleMarginUnitWidth;
path.moveTo(x, bottom);
path.lineTo(x, y + height * (1.0 - UnitHeight(_laps[0].InMillisecondsF(),
maxUnitInterval)));
double unitX;
double unitNextX = 0.0;
for (size_t i = 0; i < kMaxSamples; i += 1) {
unitX = unitNextX;
unitNextX = (static_cast<double>(i + 1) / kMaxSamples);
const double sampleY = y + height * (1.0 - UnitHeight(_laps[i].InMillisecondsF(),
maxUnitInterval));
path.lineTo(x + width * unitX + sampleMarginWidth, sampleY);
path.lineTo(x + width * unitNextX - sampleMarginWidth, sampleY);
}

path.lineTo(width, height);

path.lineTo(right, y + height * (1.0 - UnitHeight(_laps[kMaxSamples - 1].InMillisecondsF(),
maxUnitInterval)));
path.lineTo(right, bottom);
path.close();

// Draw the graph.
paint.setColor(0xAA0000FF);
canvas.drawPath(path, paint);

paint.setStrokeWidth(1);
// Draw horizontal markers.
paint.setStrokeWidth(0); // hairline
paint.setStyle(SkPaint::Style::kStroke_Style);
paint.setColor(0xAAFFFFFF);
paint.setColor(0xCC000000);

if (maxInterval > kOneFrameMS) {
// Paint the horizontal markers
Expand All @@ -116,22 +123,22 @@ void Stopwatch::visualize(SkCanvas& canvas, const SkRect& rect) const {
const double frameHeight =
height * (1.0 - (UnitFrameInterval((frameIndex + 1) * kOneFrameMS) /
maxUnitInterval));
canvas.drawLine(0, frameHeight, width, frameHeight, paint);
canvas.drawLine(x, y + frameHeight, right, y + frameHeight, paint);
}
}

// Paint the vertical marker
// Paint the vertical marker for the last frame.
paint.setStyle(SkPaint::Style::kFill_Style);
if (UnitFrameInterval(lastLap().InMillisecondsF()) > 1.0) {
// budget exceeded
paint.setColor(SK_ColorRED);
} else {
// within budget
paint.setColor(SK_ColorGREEN);
}

double sampleX = width * (static_cast<double>(_current_sample) / kMaxSamples);
paint.setStrokeWidth(3);
canvas.drawLine(sampleX, 0, sampleX, height, paint);
double sampleX = x + width * (static_cast<double>(_current_sample + 1) / kMaxSamples)
- sampleMarginWidth;
canvas.drawRectCoords(sampleX, y, sampleX + sampleMarginWidth * 2.0, bottom, paint);
}

Stopwatch::~Stopwatch() = default;
Expand Down
6 changes: 4 additions & 2 deletions flow/instrumentation.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
namespace flow {
namespace instrumentation {

static const double kOneFrameMS = 1e3 / 60.0;

class Stopwatch {
public:
class ScopedLap {
Expand All @@ -36,6 +38,8 @@ class Stopwatch {

base::TimeDelta currentLap() const { return base::TimeTicks::Now() - _start; }

base::TimeDelta maxDelta() const;

void visualize(SkCanvas& canvas, const SkRect& rect) const;

void start();
Expand All @@ -49,8 +53,6 @@ class Stopwatch {
std::vector<base::TimeDelta> _laps;
size_t _current_sample;

base::TimeDelta maxDelta() const;

DISALLOW_COPY_AND_ASSIGN(Stopwatch);
};

Expand Down
1 change: 1 addition & 0 deletions flow/layers/layer.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class Layer {

void set_parent(ContainerLayer* parent) { parent_ = parent; }

// subclasses should assume this will be true by the time Paint() is called
const bool has_paint_bounds() const { return has_paint_bounds_; }

const SkRect& paint_bounds() const {
Expand Down
42 changes: 25 additions & 17 deletions flow/layers/performance_overlay_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,33 +27,36 @@ static void DrawStatisticsText(SkCanvas& canvas,

static void VisualizeStopWatch(SkCanvas& canvas,
const instrumentation::Stopwatch& stopwatch,
SkScalar x,
SkScalar y,
SkScalar width,
SkScalar height,
bool show_graph,
bool show_labels,
std::string label_prefix) {
const int x = 8;
const int y = 70;
const int height = 80;
const int labelX = 8; // distance from x
const int labelY = -10; // distance from y+height

if (show_graph) {
SkRect visualizationRect = SkRect::MakeWH(width, height);
SkRect visualizationRect = SkRect::MakeXYWH(x, y, width, height);
stopwatch.visualize(canvas, visualizationRect);
}

if (show_labels) {
double msPerFrame = stopwatch.lastLap().InMillisecondsF();
double fps = 1e3 / msPerFrame;
double msPerFrame = stopwatch.maxDelta().InMillisecondsF();
double fps;
if (msPerFrame < instrumentation::kOneFrameMS) {
fps = 1e3 / instrumentation::kOneFrameMS;
} else {
fps = 1e3 / msPerFrame;
}

std::stringstream stream;
stream.setf(std::ios::fixed | std::ios::showpoint);
stream << std::setprecision(2);
stream << label_prefix << " " << fps << " FPS | " << msPerFrame
<< "ms/frame";
DrawStatisticsText(canvas, stream.str(), x, y);
}

if (show_labels || show_graph) {
canvas.translate(0, height);
stream << std::setprecision(1);
stream << label_prefix << " " << fps << " fps "
<< msPerFrame << "ms/frame";
DrawStatisticsText(canvas, stream.str(), x + labelX, y + height + labelY);
}
}

Expand All @@ -62,15 +65,20 @@ void PerformanceOverlayLayer::Paint(PaintContext::ScopedFrame& frame) {
return;
}

SkScalar width = has_paint_bounds() ? paint_bounds().width() : 0;
SkScalar x = paint_bounds().x();
SkScalar y = paint_bounds().y();
SkScalar width = paint_bounds().width();
SkScalar height = paint_bounds().height() / 2;
SkAutoCanvasRestore save(&frame.canvas(), true);

VisualizeStopWatch(frame.canvas(), frame.context().frame_time(), width,
VisualizeStopWatch(frame.canvas(), frame.context().frame_time(),
x, y, width, height,
options_ & kVisualizeRasterizerStatistics,
options_ & kDisplayRasterizerStatistics,
"Rasterizer");

VisualizeStopWatch(frame.canvas(), frame.context().engine_time(), width,
VisualizeStopWatch(frame.canvas(), frame.context().engine_time(),
x, y + height, width, height,
options_ & kVisualizeEngineStatistics,
options_ & kDisplayEngineStatistics,
"Engine");
Expand Down
8 changes: 4 additions & 4 deletions sky/engine/core/dart/compositing.dart
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,10 @@ class SceneBuilder extends NativeFieldWrapperClass2 {
/// controls where the statistics are displayed.
///
/// enabledOptions is a bit field with the following bits defined:
/// * 0x01: displayRasterizerStatistics - show GPU thread frame time
/// * 0x02: visualizeRasterizerStatistics - graph GPU thread frame times
/// * 0x04: displayEngineStatistics - show UI thread frame time
/// * 0x08: visualizeEngineStatistics - graph UI thread frame times
/// - 0x01: displayRasterizerStatistics - show GPU thread frame time
/// - 0x02: visualizeRasterizerStatistics - graph GPU thread frame times
/// - 0x04: displayEngineStatistics - show UI thread frame time
/// - 0x08: visualizeEngineStatistics - graph UI thread frame times
/// Set enabledOptions to 0x0F to enable all the currently defined features.
///
/// The "UI thread" is the thread that includes all the execution of
Expand Down

0 comments on commit 389bc4b

Please sign in to comment.