handle_table_perftest.cc 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. // Copyright 2017 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 "mojo/core/handle_table.h"
  5. #include "base/memory/raw_ptr.h"
  6. #include "base/synchronization/lock.h"
  7. #include "base/timer/lap_timer.h"
  8. #include "mojo/core/dispatcher.h"
  9. #include "mojo/public/c/system/types.h"
  10. #include "testing/gmock/include/gmock/gmock.h"
  11. #include "testing/gtest/include/gtest/gtest.h"
  12. #include "testing/perf/perf_result_reporter.h"
  13. namespace mojo::core {
  14. namespace {
  15. using ::base::LapTimer;
  16. using ::perf_test::PerfResultReporter;
  17. using ::testing::Eq;
  18. using ::testing::Gt;
  19. using ::testing::Ne;
  20. class FakeMessagePipeDispatcherForTesting : public Dispatcher {
  21. public:
  22. FakeMessagePipeDispatcherForTesting() = default;
  23. FakeMessagePipeDispatcherForTesting(
  24. const FakeMessagePipeDispatcherForTesting&) = delete;
  25. FakeMessagePipeDispatcherForTesting& operator=(
  26. const FakeMessagePipeDispatcherForTesting&) = delete;
  27. Type GetType() const override { return Type::MESSAGE_PIPE; }
  28. MojoResult Close() override { return MOJO_RESULT_OK; }
  29. private:
  30. ~FakeMessagePipeDispatcherForTesting() override = default;
  31. };
  32. // Returns the handles of the dispatchers added.
  33. std::vector<MojoHandle> AddDispatchersForTesting(
  34. const int num_dispatchers_to_add,
  35. HandleTable* handle_table) {
  36. std::vector<MojoHandle> handles;
  37. handles.reserve(num_dispatchers_to_add);
  38. scoped_refptr<Dispatcher> dispatcher(new FakeMessagePipeDispatcherForTesting);
  39. const base::AutoLock auto_lock(handle_table->GetLock());
  40. for (int i = 0; i < num_dispatchers_to_add; ++i) {
  41. const MojoHandle handle = handle_table->AddDispatcher(dispatcher);
  42. EXPECT_THAT(handle, Ne(MOJO_HANDLE_INVALID));
  43. handles.push_back(handle);
  44. }
  45. return handles;
  46. }
  47. constexpr char kMetricThroughput[] = "Throughput";
  48. PerfResultReporter MakeReporter(const std::string& story_name) {
  49. PerfResultReporter reporter("HandleTable", story_name);
  50. reporter.RegisterImportantMetric(kMetricThroughput, "runs/s");
  51. return reporter;
  52. }
  53. } // namespace
  54. TEST(HandleTablePerfTest, GetDispatcherDifferentHandles) {
  55. // The number below is based on https://crbug.com/1295449#c2.
  56. constexpr int kNumDispatchers = 10000;
  57. HandleTable handle_table;
  58. const std::vector<MojoHandle> handles =
  59. AddDispatchersForTesting(kNumDispatchers, &handle_table);
  60. ASSERT_THAT(handles.size(), Gt(0ul));
  61. const int handles_last_index = handles.size() - 1;
  62. int current_index = 0;
  63. LapTimer timer;
  64. // Query for dispatchers in a round-robin manner until the time limit expires.
  65. while (!timer.HasTimeLimitExpired()) {
  66. handle_table.GetDispatcher(handles[current_index]);
  67. current_index = current_index == handles_last_index ? 0 : current_index + 1;
  68. timer.NextLap();
  69. }
  70. PerfResultReporter reporter = MakeReporter("GetDispatcherDifferentHandles");
  71. reporter.AddResult(kMetricThroughput, timer.LapsPerSecond());
  72. }
  73. TEST(HandleTablePerfTest, GetDispatcherSameHandle) {
  74. // The number below is based on https://crbug.com/1295449#c2.
  75. constexpr int kNumDispatchers = 10000;
  76. HandleTable handle_table;
  77. const std::vector<MojoHandle> handles =
  78. AddDispatchersForTesting(kNumDispatchers, &handle_table);
  79. ASSERT_THAT(handles.size(), Gt(0ul));
  80. LapTimer timer;
  81. while (!timer.HasTimeLimitExpired()) {
  82. handle_table.GetDispatcher(handles[0]);
  83. timer.NextLap();
  84. }
  85. PerfResultReporter reporter = MakeReporter("GetDispatcherSameHandle");
  86. reporter.AddResult(kMetricThroughput, timer.LapsPerSecond());
  87. }
  88. TEST(HandleTablePerfTest, GetDispatcherMixedHandles) {
  89. // The number below is based on https://crbug.com/1295449#c2.
  90. constexpr int kNumDispatchers = 10000;
  91. HandleTable handle_table;
  92. const std::vector<MojoHandle> handles =
  93. AddDispatchersForTesting(kNumDispatchers, &handle_table);
  94. ASSERT_THAT(handles.size(), Gt(0ul));
  95. const int handles_last_index = handles.size() - 1;
  96. int current_index = 0;
  97. LapTimer timer;
  98. while (!timer.HasTimeLimitExpired()) {
  99. // Sample each index 3 times, thus sampling the same index as the previous
  100. // one roughly 66% of the time. Based on https://crbug.com/1295449.
  101. handle_table.GetDispatcher(handles[current_index / 4]);
  102. current_index = current_index == handles_last_index ? 0 : current_index + 1;
  103. timer.NextLap();
  104. }
  105. PerfResultReporter reporter = MakeReporter("GetDispatcherMixedHandles");
  106. reporter.AddResult(kMetricThroughput, timer.LapsPerSecond());
  107. }
  108. TEST(HandleTablePerfTest, AddAndRemoveDispatcher) {
  109. // The number below is based on https://crbug.com/1295449#c2.
  110. constexpr int kNumDispatchers = 10000;
  111. HandleTable handle_table;
  112. const std::vector<MojoHandle> handles =
  113. AddDispatchersForTesting(kNumDispatchers, &handle_table);
  114. ASSERT_THAT(handles.size(), Gt(0ul));
  115. LapTimer timer;
  116. while (!timer.HasTimeLimitExpired()) {
  117. const base::AutoLock auto_lock(handle_table.GetLock());
  118. scoped_refptr<Dispatcher> dispatcher(
  119. new FakeMessagePipeDispatcherForTesting);
  120. const MojoHandle handle = handle_table.AddDispatcher(std::move(dispatcher));
  121. EXPECT_THAT(handle, Ne(MOJO_HANDLE_INVALID));
  122. const MojoResult result =
  123. handle_table.GetAndRemoveDispatcher(handle, &dispatcher);
  124. EXPECT_THAT(result, Eq(MOJO_RESULT_OK));
  125. timer.NextLap();
  126. }
  127. PerfResultReporter reporter = MakeReporter("AddAndRemoveDispatcher");
  128. reporter.AddResult(kMetricThroughput, timer.LapsPerSecond());
  129. }
  130. } // namespace mojo::core