Improve viewer stats collection and display
authorBrian Osman <brianosman@google.com>
Thu, 9 Feb 2017 17:10:20 +0000 (12:10 -0500)
committerSkia Commit-Bot <skia-commit-bot@chromium.org>
Thu, 9 Feb 2017 17:26:09 +0000 (17:26 +0000)
Measure the time taken for animation and flush. Exclude UI and stats logic
from the timing. Use stacked bars to visualize the breakdown of time
within a frame.

BUG=skia:

Change-Id: I7ef84442a68147f02f65b6aa4452768fd3314de2
Reviewed-on: https://skia-review.googlesource.com/8227
Reviewed-by: Jim Van Verth <jvanverth@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>

tools/viewer/Viewer.cpp
tools/viewer/Viewer.h

index e25fc2e..384e9c6 100644 (file)
@@ -131,7 +131,9 @@ Viewer::Viewer(int argc, char** argv, void* platformData)
     , fZoomScale(SK_Scalar1)
 {
     SkGraphics::Init();
-    memset(fMeasurements, 0, sizeof(fMeasurements));
+    memset(fPaintTimes, 0, sizeof(fPaintTimes));
+    memset(fFlushTimes, 0, sizeof(fFlushTimes));
+    memset(fAnimateTimes, 0, sizeof(fAnimateTimes));
 
     SkDebugf("Command line arguments: ");
     for (int i = 1; i < argc; ++i) {
@@ -471,7 +473,15 @@ void Viewer::drawSlide(SkCanvas* canvas) {
     slideCanvas->concat(fDefaultMatrix);
     slideCanvas->concat(computeMatrix());
 
+    // Time the painting logic of the slide
+    double startTime = SkTime::GetMSecs();
     fSlides[fCurrentSlide]->draw(slideCanvas);
+    fPaintTimes[fCurrentMeasurement] = SkTime::GetMSecs() - startTime;
+
+    // Force a flush so we can time that, too
+    startTime = SkTime::GetMSecs();
+    slideCanvas->flush();
+    fFlushTimes[fCurrentMeasurement] = SkTime::GetMSecs() - startTime;
 
     // If we rendered offscreen, snap an image and push the results to the window's canvas
     if (offscreenSurface) {
@@ -488,20 +498,20 @@ void Viewer::drawSlide(SkCanvas* canvas) {
 }
 
 void Viewer::onPaint(SkCanvas* canvas) {
-    // Record measurements
-    double startTime = SkTime::GetMSecs();
-
     drawSlide(canvas);
 
+    // Advance our timing bookkeeping
+    fCurrentMeasurement = (fCurrentMeasurement + 1) & (kMeasurementCount - 1);
+    SkASSERT(fCurrentMeasurement < kMeasurementCount);
+
+    // Draw any overlays or UI that we don't want timed
     if (fDisplayStats) {
         drawStats(canvas);
     }
     fCommands.drawHelp(canvas);
 
-    fMeasurements[fCurrentMeasurement++] = SkTime::GetMSecs() - startTime;
-    fCurrentMeasurement &= (kMeasurementCount - 1);  // fast mod
-    SkASSERT(fCurrentMeasurement < kMeasurementCount);
-    updateUIState(); // Update the FPS
+    // Update the FPS
+    updateUIState();
 }
 
 bool Viewer::onTouch(intptr_t owner, Window::InputState state, float x, float y) {
@@ -559,10 +569,25 @@ void Viewer::drawStats(SkCanvas* canvas) {
 
     int x = SkScalarTruncToInt(rect.fLeft) + kGraphPadding;
     const int xStep = 2;
-    const int startY = SkScalarTruncToInt(rect.fBottom);
     int i = fCurrentMeasurement;
     do {
-        int endY = startY - (int)(fMeasurements[i] * kPixelPerMS + 0.5);  // round to nearest value
+        // Round to nearest values
+        int animateHeight = (int)(fAnimateTimes[i] * kPixelPerMS + 0.5);
+        int paintHeight = (int)(fPaintTimes[i] * kPixelPerMS + 0.5);
+        int flushHeight = (int)(fFlushTimes[i] * kPixelPerMS + 0.5);
+        int startY = SkScalarTruncToInt(rect.fBottom);
+        int endY = startY - flushHeight;
+        paint.setColor(SK_ColorRED);
+        canvas->drawLine(SkIntToScalar(x), SkIntToScalar(startY),
+                         SkIntToScalar(x), SkIntToScalar(endY), paint);
+        startY = endY;
+        endY = startY - paintHeight;
+        paint.setColor(SK_ColorGREEN);
+        canvas->drawLine(SkIntToScalar(x), SkIntToScalar(startY),
+                         SkIntToScalar(x), SkIntToScalar(endY), paint);
+        startY = endY;
+        endY = startY - animateHeight;
+        paint.setColor(SK_ColorMAGENTA);
         canvas->drawLine(SkIntToScalar(x), SkIntToScalar(startY),
                          SkIntToScalar(x), SkIntToScalar(endY), paint);
         i++;
@@ -574,8 +599,12 @@ void Viewer::drawStats(SkCanvas* canvas) {
 }
 
 void Viewer::onIdle() {
+    double startTime = SkTime::GetMSecs();
     fAnimTimer.updateTime();
-    if (fSlides[fCurrentSlide]->animate(fAnimTimer) || fDisplayStats || fRefresh) {
+    bool animateWantsInval = fSlides[fCurrentSlide]->animate(fAnimTimer);
+    fAnimateTimes[fCurrentMeasurement] = SkTime::GetMSecs() - startTime;
+
+    if (animateWantsInval || fDisplayStats || fRefresh) {
         fWindow->inval();
     }
 }
@@ -614,10 +643,12 @@ void Viewer::updateUIState() {
     // FPS state
     Json::Value fpsState(Json::objectValue);
     fpsState[kName] = kFpsStateName;
-    double measurement = fMeasurements[
-            (fCurrentMeasurement + (kMeasurementCount-1)) % kMeasurementCount
-    ];
-    fpsState[kValue] = SkStringPrintf("%8.3lf ms", measurement).c_str();
+    int idx = (fCurrentMeasurement + (kMeasurementCount - 1)) & (kMeasurementCount - 1);
+    fpsState[kValue] = SkStringPrintf("%8.3lf ms\n\nA %8.3lf\nP %8.3lf\nF%8.3lf",
+                                      fAnimateTimes[idx] + fPaintTimes[idx] + fFlushTimes[idx],
+                                      fAnimateTimes[idx],
+                                      fPaintTimes[idx],
+                                      fFlushTimes[idx]).c_str();
     fpsState[kOptions] = Json::Value(Json::arrayValue);
 
     Json::Value state(Json::arrayValue);
index 1608fa9..7b08df5 100644 (file)
@@ -45,7 +45,9 @@ private:
     sk_app::Window*        fWindow;
 
     static const int kMeasurementCount = 64;  // should be power of 2 for fast mod
-    double fMeasurements[kMeasurementCount];
+    double fPaintTimes[kMeasurementCount];
+    double fFlushTimes[kMeasurementCount];
+    double fAnimateTimes[kMeasurementCount];
     int fCurrentMeasurement;
 
     SkAnimTimer            fAnimTimer;