Bug 1256408 - Add graphics microbenchmarking. r=mstange draft
authorBenoit Girard <b56girard@gmail.com>
Wed, 16 Mar 2016 14:20:33 -0400
changeset 341178 8eed4669b59496370dbc47d32e2696de60ea43f2
parent 339972 7ac16df5c769fb60f438f4087f760d4d00af56a9
child 516361 2ebcdcd1d6ad8bad162477651e61f748313e23a4
push id13165
push userb56girard@gmail.com
push dateWed, 16 Mar 2016 18:20:42 +0000
reviewersmstange
bugs1256408
milestone48.0a1
Bug 1256408 - Add graphics microbenchmarking. r=mstange MozReview-Commit-ID: H4IRZuLy7do
gfx/tests/gtest/TestCompositor.cpp
gfx/tests/gtest/TestRegion.cpp
testing/gtest/moz.build
testing/gtest/mozilla/MozGTestBench.cpp
testing/gtest/mozilla/MozGTestBench.h
--- a/gfx/tests/gtest/TestCompositor.cpp
+++ b/gfx/tests/gtest/TestCompositor.cpp
@@ -1,16 +1,17 @@
 /* vim:set ts=2 sw=2 sts=2 et: */
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 #include "gfxPrefs.h"
 #include "gfxUtils.h"
 #include "gtest/gtest.h"
+#include "gtest/MozGTestBench.h"
 #include "TestLayers.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/layers/BasicCompositor.h"  // for BasicCompositor
 #include "mozilla/layers/Compositor.h"  // for Compositor
 #include "mozilla/layers/CompositorOGL.h"  // for CompositorOGL
 #include "mozilla/layers/CompositorTypes.h"
 #include "mozilla/layers/LayerManagerComposite.h"
@@ -222,49 +223,56 @@ static bool CompositeAndCompare(RefPtr<L
   return true;
 }
 
 TEST(Gfx, CompositorConstruct)
 {
   auto layerManagers = GetLayerManagers(GetPlatformBackends());
 }
 
-TEST(Gfx, CompositorSimpleTree)
-{
+static void CompositorSimpleTree() {
+  const int benchmarkRepeatCount = 30;
+
+  RefPtr<DrawTarget> refDT = CreateDT();
+  refDT->FillRect(Rect(0, 0, gCompWidth, gCompHeight), ColorPattern(Color(1.f, 0.f, 1.f, 1.f)));
+  refDT->FillRect(Rect(0, 0, 100, 100), ColorPattern(Color(1.f, 0.f, 0.f, 1.f)));
+  refDT->FillRect(Rect(0, 50, 100, 100), ColorPattern(Color(0.f, 0.f, 1.f, 1.f)));
+
   auto layerManagers = GetLayerManagers(GetPlatformBackends());
   for (size_t i = 0; i < layerManagers.size(); i++) {
-    RefPtr<LayerManagerComposite> layerManager = layerManagers[i].mLayerManager;
-    RefPtr<LayerManager> lmBase = layerManager.get();
-    nsTArray<RefPtr<Layer>> layers;
-    nsIntRegion layerVisibleRegion[] = {
-      nsIntRegion(IntRect(0, 0, gCompWidth, gCompHeight)),
-      nsIntRegion(IntRect(0, 0, gCompWidth, gCompHeight)),
-      nsIntRegion(IntRect(0, 0, 100, 100)),
-      nsIntRegion(IntRect(0, 50, 100, 100)),
-    };
-    RefPtr<Layer> root = CreateLayerTree("c(ooo)", layerVisibleRegion, nullptr, lmBase, layers);
+    // Benchmark n composites
+    for (size_t n = 0; n < benchmarkRepeatCount; n++) {
+      RefPtr<LayerManagerComposite> layerManager = layerManagers[i].mLayerManager;
+      RefPtr<LayerManager> lmBase = layerManager.get();
+      nsTArray<RefPtr<Layer>> layers;
+      nsIntRegion layerVisibleRegion[] = {
+        nsIntRegion(IntRect(0, 0, gCompWidth, gCompHeight)),
+        nsIntRegion(IntRect(0, 0, gCompWidth, gCompHeight)),
+        nsIntRegion(IntRect(0, 0, 100, 100)),
+        nsIntRegion(IntRect(0, 50, 100, 100)),
+      };
+      RefPtr<Layer> root = CreateLayerTree("c(ooo)", layerVisibleRegion, nullptr, lmBase, layers);
 
-    { // background
-      ColorLayer* colorLayer = layers[1]->AsColorLayer();
-      colorLayer->SetColor(Color(1.f, 0.f, 1.f, 1.f));
-      colorLayer->SetBounds(colorLayer->GetVisibleRegion().ToUnknownRegion().GetBounds());
-    }
+      { // background
+        ColorLayer* colorLayer = layers[1]->AsColorLayer();
+        colorLayer->SetColor(Color(1.f, 0.f, 1.f, 1.f));
+        colorLayer->SetBounds(colorLayer->GetVisibleRegion().ToUnknownRegion().GetBounds());
+      }
 
-    {
-      ColorLayer* colorLayer = layers[2]->AsColorLayer();
-      colorLayer->SetColor(Color(1.f, 0.f, 0.f, 1.f));
-      colorLayer->SetBounds(colorLayer->GetVisibleRegion().ToUnknownRegion().GetBounds());
-    }
+      {
+        ColorLayer* colorLayer = layers[2]->AsColorLayer();
+        colorLayer->SetColor(Color(1.f, 0.f, 0.f, 1.f));
+        colorLayer->SetBounds(colorLayer->GetVisibleRegion().ToUnknownRegion().GetBounds());
+      }
 
-    {
-      ColorLayer* colorLayer = layers[3]->AsColorLayer();
-      colorLayer->SetColor(Color(0.f, 0.f, 1.f, 1.f));
-      colorLayer->SetBounds(colorLayer->GetVisibleRegion().ToUnknownRegion().GetBounds());
-    }
+      {
+        ColorLayer* colorLayer = layers[3]->AsColorLayer();
+        colorLayer->SetColor(Color(0.f, 0.f, 1.f, 1.f));
+        colorLayer->SetBounds(colorLayer->GetVisibleRegion().ToUnknownRegion().GetBounds());
+      }
 
-    RefPtr<DrawTarget> refDT = CreateDT();
-    refDT->FillRect(Rect(0, 0, gCompWidth, gCompHeight), ColorPattern(Color(1.f, 0.f, 1.f, 1.f)));
-    refDT->FillRect(Rect(0, 0, 100, 100), ColorPattern(Color(1.f, 0.f, 0.f, 1.f)));
-    refDT->FillRect(Rect(0, 50, 100, 100), ColorPattern(Color(0.f, 0.f, 1.f, 1.f)));
-    EXPECT_TRUE(CompositeAndCompare(layerManager, refDT));
+      EXPECT_TRUE(CompositeAndCompare(layerManager, refDT));
+    }
   }
-}
+};
 
+MOZ_GTEST_BENCH(GfxBench, CompositorSimpleTree, &CompositorSimpleTree);
+
--- a/gfx/tests/gtest/TestRegion.cpp
+++ b/gfx/tests/gtest/TestRegion.cpp
@@ -1,16 +1,18 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include <algorithm>
 
 #include "gtest/gtest.h"
+#include "gtest/MozGTestBench.h"
+#include "nsRect.h"
 #include "nsRegion.h"
 
 using namespace std;
 
 class TestLargestRegion {
 public:
   static void TestSingleRect(nsRect r) {
     nsRegion region(r);
@@ -557,8 +559,27 @@ TEST(Gfx, RegionVisitEdges) {
     r.Or(r, nsRect(25, 50, 28, 5));
     r.Or(r, nsRect(115, 50, 99, 5));
     r.Or(r, nsRect(115, 55, 99, 12));
 
     TestVisit(r);
   }
 
 }
+
+MOZ_GTEST_BENCH(GfxBench, RegionOr, []{
+  const int size = 5000;
+  nsRegion r;
+  for (int i = 0; i < size; i++) {
+    r = r.Or(r, nsRect(i, i, i + 10, i + 10));
+  }
+});
+
+MOZ_GTEST_BENCH(GfxBench, RegionAnd, []{
+  const int size = 5000;
+  nsRegion r(nsRect(0, 0, size, size));
+  for (int i = 0; i < size; i++) {
+    nsRegion rMissingPixel(nsRect(0, 0, size, size));
+    rMissingPixel = rMissingPixel.Sub(rMissingPixel, nsRect(i, i, 1, 1));
+    r = r.And(r, rMissingPixel);
+  }
+});
+
--- a/testing/gtest/moz.build
+++ b/testing/gtest/moz.build
@@ -15,16 +15,17 @@ if CONFIG['ENABLE_TESTS']:
         'gtest/include/gtest/gtest-param-test.h',
         'gtest/include/gtest/gtest-printers.h',
         'gtest/include/gtest/gtest-spi.h',
         'gtest/include/gtest/gtest-test-part.h',
         'gtest/include/gtest/gtest-typed-test.h',
         'gtest/include/gtest/gtest.h',
         'gtest/include/gtest/gtest_pred_impl.h',
         'gtest/include/gtest/gtest_prod.h',
+        'mozilla/MozGTestBench.h',
     ]
 
     # GTest internal are exposed in gtest.h. See comment in gtest.h
     EXPORTS.gtest.internal += [
         'gtest/include/gtest/internal/gtest-death-test-internal.h',
         'gtest/include/gtest/internal/gtest-filepath.h',
         'gtest/include/gtest/internal/gtest-internal.h',
         'gtest/include/gtest/internal/gtest-linked_ptr.h',
@@ -55,16 +56,17 @@ if CONFIG['ENABLE_TESTS']:
         'gmock/include/gmock/internal/gmock-internal-utils.h',
         'gmock/include/gmock/internal/gmock-port.h',
     ]
 
     SOURCES += [
         'gmock/src/gmock-all.cc',
         'gtest/src/gtest-all.cc',
         'mozilla/GTestRunner.cpp',
+        'mozilla/MozGTestBench.cpp',
     ]
 
     Library('gtest')
 
     SOURCES += [
         'mozilla/SanityTest.cpp',
     ]
 
new file mode 100644
--- /dev/null
+++ b/testing/gtest/mozilla/MozGTestBench.cpp
@@ -0,0 +1,39 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "MozGTestBench.h"
+#include "mozilla/TimeStamp.h"
+#include <stdio.h>
+
+#define MOZ_GTEST_BENCH_FRAMEWORK "platform_microbench"
+
+using mozilla::TimeStamp;
+
+namespace mozilla {
+void GTestBench(const char* aSuite, const char* aName,
+                const mozilla::function<void()>& aTest)
+{
+#ifdef DEBUG
+  // Run the test to make sure that it doesn't fail but don't log
+  // any measurements since it's not an optimized build.
+  aTest();
+#else
+  mozilla::TimeStamp start = TimeStamp::Now();
+
+  aTest();
+
+  int msDuration = (TimeStamp::Now() - start).ToMicroseconds();
+
+  // Print the result for each test. Let perfherder aggregate for us
+  printf("PERFHERDER_DATA: {\"framework\": {\"name\": \"%s\"}, "
+                           "\"suites\": [{\"name\": \"%s\", \"subtests\": "
+                               "[{\"name\": \"%s\", \"value\": %i, \"lowerIsBetter\": true}]"
+                           "}]}\n",
+                           MOZ_GTEST_BENCH_FRAMEWORK, aSuite, aName, msDuration);
+#endif
+}
+
+} // mozilla
+
new file mode 100644
--- /dev/null
+++ b/testing/gtest/mozilla/MozGTestBench.h
@@ -0,0 +1,22 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef GTEST_MOZGTESTBENCH_H
+#define GTEST_MOZGTESTBENCH_H
+
+#include "mozilla/Function.h"
+
+namespace mozilla {
+
+void GTestBench(const char* aSuite, const char* aName, const mozilla::function<void()>& aTest);
+
+} //mozilla
+
+#define MOZ_GTEST_BENCH(suite, test, lambdaOrFunc) \
+TEST(suite, test) { \
+  mozilla::GTestBench(#suite, #test, lambdaOrFunc); \
+}
+
+#endif // GTEST_MOZGTESTBENCH_H