Index: ui/views/controls/button/label_button_perftest.cc |
diff --git a/ui/views/controls/button/label_button_perftest.cc b/ui/views/controls/button/label_button_perftest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..186ab997e6a2a167f19cd70370a46bf69297bb28 |
--- /dev/null |
+++ b/ui/views/controls/button/label_button_perftest.cc |
@@ -0,0 +1,147 @@ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "ui/views/controls/button/label_button.h" |
+ |
+#include "base/strings/utf_string_conversions.h" |
+#include "base/test/perf_time_logger.h" |
+#include "cc/playback/display_item_list.h" |
+#include "cc/playback/display_item_list_settings.h" |
+#include "ui/compositor/paint_context.h" |
+#include "ui/views/test/widget_test.h" |
+ |
+namespace views { |
+namespace { |
+ |
+const int kWarmupIterations = 20; |
+const int kScaleFactor = 2.0f; // Test HiDPI. |
+ |
+class LabelButtonPerfTest : public test::WidgetTest { |
+ public: |
+ LabelButtonPerfTest() {} |
+ |
+ // Body of the test after a button has been created. Goal is to simulate the |
+ // impact of adding one additional button on the time to first paint a dialog. |
+ void PostCreateTestBody(const ui::PaintContext& paint_context, View* view) { |
+ view->SizeToPreferredSize(); |
+ widget_->GetContentsView()->AddChildView(view); |
+ widget_->GetContentsView()->Layout(); |
+ // Paint into a new canvas. This gets adopted by the View's PaintCache to |
+ // emulate a "first" paint scenario. Paints the root view, so that the |
+ // PaintContext can be reused. |
+ widget_->GetRootView()->Paint(paint_context); |
+ } |
+ |
+ void RunViewInitPaintTest(const char* test_name, |
+ const base::Callback<View*()>& factory, |
+ int perf_test_iterations) { |
+ // Create a template view to determine size and ensure resources are loaded |
+ // for the given scale factor. |
+ gfx::Rect canvas_rect; |
+ { |
+ const gfx::Rect template_rect(100, 100); |
+ scoped_refptr<cc::DisplayItemList> list = cc::DisplayItemList::Create( |
+ template_rect, cc::DisplayItemListSettings()); |
+ ui::PaintContext paint_context(list.get(), kScaleFactor, template_rect, |
+ template_rect); |
+ scoped_ptr<View> template_view(factory.Run()); |
+ PostCreateTestBody(paint_context, template_view.get()); |
+ canvas_rect = template_view->bounds(); |
+ } |
+ |
+ // Sanity check to ensure something is happening. |
+ EXPECT_LT(10, canvas_rect.width()); |
+ EXPECT_LT(10, canvas_rect.height()); |
+ |
+ // Repaint with the same PaintContext each time. |
+ scoped_refptr<cc::DisplayItemList> list = |
+ cc::DisplayItemList::Create(canvas_rect, cc::DisplayItemListSettings()); |
+ ui::PaintContext paint_context(list.get(), kScaleFactor, canvas_rect, |
+ canvas_rect); |
+ |
+ for (int iteration = 0; iteration < kWarmupIterations; ++iteration) { |
+ scoped_ptr<View> view(factory.Run()); |
+ PostCreateTestBody(paint_context, view.get()); |
+ } |
+ |
+ base::PerfTimeLogger timer(test_name); |
+ for (int iteration = 0; iteration < perf_test_iterations; ++iteration) { |
+ scoped_ptr<View> view(factory.Run()); |
+ PostCreateTestBody(paint_context, view.get()); |
+ // scoped_ptr destructor removes the button from the hierarchy. |
+ } |
+ // PerfTimeLogger destructor logs duration. |
+ } |
+ |
+ // testing::Test: |
+ void SetUp() override { |
+ ViewsTestBase::SetUp(); |
+ // Some initialization (e.g. for theming) does not occur until a view is |
+ // actually added to a widget. Create a widget for that, but don't ever show |
+ // it nor paint it. |
+ widget_ = CreateTopLevelPlatformWidget(); |
+ widget_->SetSize(gfx::Size(200, 200)); |
+ widget_->Show(); |
+ } |
+ |
+ void TearDown() override { |
+ widget_->CloseNow(); |
+ ViewsTestBase::TearDown(); |
+ } |
+ |
+ protected: |
+ Widget* widget_ = nullptr; |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(LabelButtonPerfTest); |
+}; |
+ |
+// Factory functions for the test. Try to mimic the manner by which Views are |
+// are typically created in client code. |
+View* CreateTextbutton(const base::string16& text) { |
+ return new LabelButton(nullptr, text); |
+} |
+ |
+View* CreateButton(const base::string16& text) { |
+ LabelButton* button = new LabelButton(nullptr, text); |
+ button->SetStyle(Button::STYLE_BUTTON); |
+ return button; |
+} |
+ |
+} // namespace |
+ |
+// Performance tests for initializing a LabelButton, adding it to a View |
+// hierarchy, then performing a "first" paint. Ballpark figures are given for |
+// the duration of a single iteration on a z620 running Linux. |
+ |
+// Test STYLE_TEXTBUTTON with no text. Ballpark: 1ms debug 0.3ms release. |
+TEST_F(LabelButtonPerfTest, InitAndPaintTextbuttonNoText) { |
+ RunViewInitPaintTest("views_label_button_text_button_no_text_1000", |
+ base::Bind(&CreateTextbutton, base::string16()), |
+ 1000); |
+} |
+ |
+// Test STYLE_TEXTBUTTON with the label "abc". Ballpark: 8ms debug, 7ms release. |
+TEST_F(LabelButtonPerfTest, InitAndPaintTextbuttonAbcText) { |
+ RunViewInitPaintTest( |
+ "views_label_button_text_button_abc_text_100", |
+ base::Bind(&CreateTextbutton, base::ASCIIToUTF16("abc")), |
+ 100); |
+} |
+ |
+// Test STYLE_BUTTON with no text. Ballpark: 2.5ms debug 1ms release. |
+TEST_F(LabelButtonPerfTest, InitAndPaintButtonNoText) { |
+ RunViewInitPaintTest("views_label_button_button_no_text_1000", |
+ base::Bind(&CreateButton, base::string16()), |
+ 1000); |
+} |
+ |
+// Test STYLE_BUTTON with the label "abc". Ballpark: 12ms debug, 9ms release. |
+TEST_F(LabelButtonPerfTest, InitAndPaintButtonAbcText) { |
+ RunViewInitPaintTest("views_label_button_button_abc_text_100", |
+ base::Bind(&CreateButton, base::ASCIIToUTF16("abc")), |
+ 100); |
+} |
+ |
+} // namespace views |