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