ax_node_position_perftest.cc 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. // Copyright 2019 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "base/strings/stringprintf.h"
  5. #include "base/timer/lap_timer.h"
  6. #include "testing/gtest/include/gtest/gtest.h"
  7. #include "testing/perf/perf_result_reporter.h"
  8. #include "ui/accessibility/ax_node_position.h"
  9. #include "ui/accessibility/ax_tree_id.h"
  10. #include "ui/accessibility/ax_tree_update.h"
  11. #include "ui/accessibility/test_ax_tree_manager.h"
  12. namespace ui {
  13. using TestPositionType = std::unique_ptr<AXPosition<AXNodePosition, AXNode>>;
  14. namespace {
  15. constexpr int kLaps = 5000;
  16. constexpr int kWarmupLaps = 5;
  17. constexpr char kMetricCallsPerSecondRunsPerS[] = "calls_per_second";
  18. class AXPositionPerfTest : public ::testing::Test, public TestAXTreeManager {
  19. public:
  20. AXPositionPerfTest() = default;
  21. AXPositionPerfTest(const AXPositionPerfTest&) = delete;
  22. AXPositionPerfTest& operator=(const AXPositionPerfTest&) = delete;
  23. ~AXPositionPerfTest() override = default;
  24. protected:
  25. void SetUp() override;
  26. perf_test::PerfResultReporter SetUpReporter(const std::string& story) {
  27. perf_test::PerfResultReporter reporter("AXPositionPerfTest.", story);
  28. reporter.RegisterImportantMetric(kMetricCallsPerSecondRunsPerS, "runs/s");
  29. return reporter;
  30. }
  31. };
  32. void AXPositionPerfTest::SetUp() {
  33. // Setup a root with 5 child kGenericContainer with 5 kStaticText each.
  34. // Each kStaticText contains 5 characters of text.
  35. //
  36. // +------------------------+--------------+
  37. // | Tree Hierarchy + Role | anchor_id(s) |
  38. // +------------------------+--------------+
  39. // | ++kRootWebArea | 1 |
  40. // | ++++kGenericContainer | 2 |
  41. // | ++++++kStaticText | 7 - 11 |
  42. // | ++++kGenericContainer | 3 |
  43. // | ++++++kStaticText | 12 - 16 |
  44. // | ++++kGenericContainer | 4 |
  45. // | ++++++kStaticText | 17 - 21 |
  46. // | ++++kGenericContainer | 5 |
  47. // | ++++++kStaticText | 22 - 26 |
  48. // | ++++kGenericContainer | 6 |
  49. // | ++++++kStaticText | 27 - 31 |
  50. // +------------------------+--------------+
  51. constexpr int kNumberOfGroups = 5;
  52. constexpr int kStaticTextNodesPerGroup = 5;
  53. constexpr int kNumberOfStaticTextNodes =
  54. kNumberOfGroups * kStaticTextNodesPerGroup;
  55. constexpr int kGroupNodesStartIndex = 1;
  56. constexpr int kStaticTextNodesStartIndex =
  57. kGroupNodesStartIndex + kNumberOfGroups;
  58. AXNodeID current_id = 0;
  59. std::vector<AXNodeData> nodes;
  60. nodes.resize(1 + kNumberOfGroups + kNumberOfStaticTextNodes);
  61. AXNodeData& root_data = nodes[0];
  62. root_data.id = ++current_id;
  63. root_data.role = ax::mojom::Role::kRootWebArea;
  64. for (int group_index = 0; group_index < kNumberOfGroups; ++group_index) {
  65. AXNodeData& group = nodes[kGroupNodesStartIndex + group_index];
  66. group.id = ++current_id;
  67. group.role = ax::mojom::Role::kGenericContainer;
  68. root_data.child_ids.push_back(group.id);
  69. }
  70. for (int text_index = 0; text_index < kNumberOfStaticTextNodes;
  71. ++text_index) {
  72. const int group_index = text_index / kStaticTextNodesPerGroup;
  73. AXNodeData& group = nodes[kGroupNodesStartIndex + group_index];
  74. AXNodeData& static_text = nodes[kStaticTextNodesStartIndex + text_index];
  75. static_text.id = ++current_id;
  76. static_text.role = ax::mojom::Role::kStaticText;
  77. static_text.SetName(base::StringPrintf("id_%02X", static_text.id));
  78. group.child_ids.push_back(static_text.id);
  79. }
  80. AXTreeUpdate initial_state;
  81. initial_state.root_id = nodes[0].id;
  82. initial_state.nodes = nodes;
  83. initial_state.has_tree_data = true;
  84. initial_state.tree_data.tree_id = AXTreeID::CreateNewAXTreeID();
  85. initial_state.tree_data.title = "Perftest title";
  86. SetTree(std::make_unique<AXTree>(initial_state));
  87. }
  88. } // namespace
  89. TEST_F(AXPositionPerfTest, AsTreePositionFromTextPosition) {
  90. TestPositionType text_position = AXNodePosition::CreateTextPosition(
  91. GetTreeID(), /*anchor_id=*/1, /*text_offset=*/103,
  92. ax::mojom::TextAffinity::kDownstream);
  93. // The time limit is unused. Use kLaps for the check interval so the time is
  94. // only measured once.
  95. base::LapTimer timer(kWarmupLaps, base::TimeDelta(), kLaps);
  96. for (int i = 0; i < kLaps + kWarmupLaps; ++i) {
  97. TestPositionType as_tree_position = text_position->AsTreePosition();
  98. timer.NextLap();
  99. }
  100. auto reporter = SetUpReporter("AsTreePositionFromTextPosition");
  101. reporter.AddResult(kMetricCallsPerSecondRunsPerS, timer.LapsPerSecond());
  102. }
  103. TEST_F(AXPositionPerfTest, AsLeafTextPositionFromTextPosition) {
  104. TestPositionType text_position = AXNodePosition::CreateTextPosition(
  105. GetTreeID(), /*anchor_id=*/1, /*text_offset=*/103,
  106. ax::mojom::TextAffinity::kDownstream);
  107. // The time limit is unused. Use kLaps for the check interval so the time is
  108. // only measured once.
  109. base::LapTimer timer(kWarmupLaps, base::TimeDelta(), kLaps);
  110. for (int i = 0; i < kLaps + kWarmupLaps; ++i) {
  111. TestPositionType as_tree_position = text_position->AsLeafTextPosition();
  112. timer.NextLap();
  113. }
  114. auto reporter = SetUpReporter("AsLeafTextPositionFromTextPosition");
  115. reporter.AddResult(kMetricCallsPerSecondRunsPerS, timer.LapsPerSecond());
  116. }
  117. TEST_F(AXPositionPerfTest, AsLeafTextPositionFromTreePosition) {
  118. TestPositionType tree_position = AXNodePosition::CreateTreePosition(
  119. GetTreeID(), /*anchor_id=*/1, /*child_index=*/4);
  120. base::LapTimer timer(kWarmupLaps, base::TimeDelta(), kLaps);
  121. for (int i = 0; i < kLaps + kWarmupLaps; ++i) {
  122. TestPositionType as_tree_position = tree_position->AsLeafTextPosition();
  123. timer.NextLap();
  124. }
  125. auto reporter = SetUpReporter("AsLeafTextPositionFromTreePosition");
  126. reporter.AddResult(kMetricCallsPerSecondRunsPerS, timer.LapsPerSecond());
  127. }
  128. TEST_F(AXPositionPerfTest, CompareTextPositions) {
  129. TestPositionType text_position_1 = AXNodePosition::CreateTextPosition(
  130. GetTreeID(), /*anchor_id=*/7, /*text_offset=*/1,
  131. ax::mojom::TextAffinity::kDownstream);
  132. TestPositionType text_position_2 = AXNodePosition::CreateTextPosition(
  133. GetTreeID(), /*anchor_id=*/27, /*text_offset=*/1,
  134. ax::mojom::TextAffinity::kDownstream);
  135. base::LapTimer timer(kWarmupLaps, base::TimeDelta(), kLaps);
  136. for (int i = 0; i < kLaps + kWarmupLaps; ++i) {
  137. text_position_1->CompareTo(*text_position_2);
  138. timer.NextLap();
  139. }
  140. auto reporter = SetUpReporter("CompareTextPositions");
  141. reporter.AddResult(kMetricCallsPerSecondRunsPerS, timer.LapsPerSecond());
  142. }
  143. } // namespace ui