• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 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 
5 #include <stdint.h>
6 
7 #include <string>
8 #include <utility>
9 
10 #include "base/auto_reset.h"
11 #include "base/bind.h"
12 #include "base/macros.h"
13 #include "base/memory/scoped_vector.h"
14 #include "base/run_loop.h"
15 #include "base/time/time.h"
16 #include "mojo/message_pump/handle_watcher.h"
17 #include "mojo/message_pump/message_pump_mojo.h"
18 #include "mojo/public/cpp/test_support/test_support.h"
19 #include "mojo/public/cpp/test_support/test_utils.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21 
22 namespace mojo {
23 namespace common {
24 namespace test {
25 
26 enum MessageLoopConfig {
27   MESSAGE_LOOP_CONFIG_DEFAULT = 0,
28   MESSAGE_LOOP_CONFIG_MOJO = 1
29 };
30 
CreateMessageLoop(MessageLoopConfig config)31 std::unique_ptr<base::MessageLoop> CreateMessageLoop(MessageLoopConfig config) {
32   std::unique_ptr<base::MessageLoop> loop;
33   if (config == MESSAGE_LOOP_CONFIG_DEFAULT)
34     loop.reset(new base::MessageLoop());
35   else
36     loop.reset(new base::MessageLoop(MessagePumpMojo::Create()));
37   return loop;
38 }
39 
OnWatcherSignaled(const base::Closure & callback,MojoResult)40 void OnWatcherSignaled(const base::Closure& callback, MojoResult /* result */) {
41   callback.Run();
42 }
43 
44 class ScopedPerfTimer {
45  public:
ScopedPerfTimer(const std::string & test_name,const std::string & sub_test_name,uint64_t iterations)46   ScopedPerfTimer(const std::string& test_name,
47                   const std::string& sub_test_name,
48                   uint64_t iterations)
49       : test_name_(test_name),
50         sub_test_name_(sub_test_name),
51         iterations_(iterations),
52         start_time_(base::TimeTicks::Now()) {}
~ScopedPerfTimer()53   ~ScopedPerfTimer() {
54     base::TimeTicks end_time = base::TimeTicks::Now();
55     mojo::test::LogPerfResult(
56         test_name_.c_str(), sub_test_name_.c_str(),
57         iterations_ / (end_time - start_time_).InSecondsF(),
58         "iterations/second");
59   }
60 
61  private:
62   const std::string test_name_;
63   const std::string sub_test_name_;
64   const uint64_t iterations_;
65   base::TimeTicks start_time_;
66 
67   DISALLOW_COPY_AND_ASSIGN(ScopedPerfTimer);
68 };
69 
70 class HandleWatcherPerftest : public testing::TestWithParam<MessageLoopConfig> {
71  public:
HandleWatcherPerftest()72   HandleWatcherPerftest() : message_loop_(CreateMessageLoop(GetParam())) {}
73 
74  protected:
GetMessageLoopName() const75   std::string GetMessageLoopName() const {
76     return (GetParam() == MESSAGE_LOOP_CONFIG_DEFAULT) ? "DefaultMessageLoop"
77                                                        : "MojoMessageLoop";
78   }
79 
80  private:
81   std::unique_ptr<base::MessageLoop> message_loop_;
82 
83   DISALLOW_COPY_AND_ASSIGN(HandleWatcherPerftest);
84 };
85 
86 INSTANTIATE_TEST_CASE_P(MultipleMessageLoopConfigs,
87                         HandleWatcherPerftest,
88                         testing::Values(MESSAGE_LOOP_CONFIG_DEFAULT,
89                                         MESSAGE_LOOP_CONFIG_MOJO));
90 
NeverReached(MojoResult result)91 void NeverReached(MojoResult result) {
92   FAIL() << "Callback should never be invoked " << result;
93 }
94 
TEST_P(HandleWatcherPerftest,StartStop)95 TEST_P(HandleWatcherPerftest, StartStop) {
96   const uint64_t kIterations = 100000;
97   MessagePipe pipe;
98   HandleWatcher watcher;
99 
100   ScopedPerfTimer timer("StartStop", GetMessageLoopName(), kIterations);
101   for (uint64_t i = 0; i < kIterations; i++) {
102     watcher.Start(pipe.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE,
103                   MOJO_DEADLINE_INDEFINITE, base::Bind(&NeverReached));
104     watcher.Stop();
105   }
106 }
107 
TEST_P(HandleWatcherPerftest,StartAllThenStop_1000Handles)108 TEST_P(HandleWatcherPerftest, StartAllThenStop_1000Handles) {
109   const uint64_t kIterations = 100;
110   const uint64_t kHandles = 1000;
111 
112   struct TestData {
113     MessagePipe pipe;
114     HandleWatcher watcher;
115   };
116   ScopedVector<TestData> data_vector;
117   // Create separately from the start/stop loops to avoid affecting the
118   // benchmark.
119   for (uint64_t i = 0; i < kHandles; i++) {
120     std::unique_ptr<TestData> test_data(new TestData);
121     ASSERT_TRUE(test_data->pipe.handle0.is_valid());
122     data_vector.push_back(std::move(test_data));
123   }
124 
125   ScopedPerfTimer timer("StartAllThenStop_1000Handles", GetMessageLoopName(),
126                         kIterations * kHandles);
127   for (uint64_t iter = 0; iter < kIterations; iter++) {
128     for (uint64_t i = 0; i < kHandles; i++) {
129       TestData* test_data = data_vector[i];
130       test_data->watcher.Start(
131           test_data->pipe.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE,
132           MOJO_DEADLINE_INDEFINITE, base::Bind(&NeverReached));
133     }
134     for (uint64_t i = 0; i < kHandles; i++) {
135       TestData* test_data = data_vector[i];
136       test_data->watcher.Stop();
137     }
138   }
139 }
140 
TEST_P(HandleWatcherPerftest,StartAndSignal)141 TEST_P(HandleWatcherPerftest, StartAndSignal) {
142   const uint64_t kIterations = 10000;
143   const std::string kMessage = "hello";
144   MessagePipe pipe;
145   HandleWatcher watcher;
146   std::string received_message;
147 
148   ScopedPerfTimer timer("StartAndSignal", GetMessageLoopName(), kIterations);
149   for (uint64_t i = 0; i < kIterations; i++) {
150     base::RunLoop run_loop;
151     watcher.Start(pipe.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE,
152                   MOJO_DEADLINE_INDEFINITE,
153                   base::Bind(&OnWatcherSignaled, run_loop.QuitClosure()));
154     ASSERT_TRUE(mojo::test::WriteTextMessage(pipe.handle1.get(), kMessage));
155     run_loop.Run();
156     watcher.Stop();
157 
158     ASSERT_TRUE(
159         mojo::test::ReadTextMessage(pipe.handle0.get(), &received_message));
160     EXPECT_EQ(kMessage, received_message);
161     received_message.clear();
162   }
163 }
164 
TEST_P(HandleWatcherPerftest,StartAndSignal_1000Waiting)165 TEST_P(HandleWatcherPerftest, StartAndSignal_1000Waiting) {
166   const uint64_t kIterations = 10000;
167   const uint64_t kWaitingHandles = 1000;
168   const std::string kMessage = "hello";
169   MessagePipe pipe;
170   HandleWatcher watcher;
171   std::string received_message;
172 
173   struct TestData {
174     MessagePipe pipe;
175     HandleWatcher watcher;
176   };
177   ScopedVector<TestData> data_vector;
178   for (uint64_t i = 0; i < kWaitingHandles; i++) {
179     std::unique_ptr<TestData> test_data(new TestData);
180     ASSERT_TRUE(test_data->pipe.handle0.is_valid());
181     test_data->watcher.Start(
182         test_data->pipe.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE,
183         MOJO_DEADLINE_INDEFINITE, base::Bind(&NeverReached));
184     data_vector.push_back(std::move(test_data));
185   }
186 
187   ScopedPerfTimer timer("StartAndSignal_1000Waiting", GetMessageLoopName(),
188                         kIterations);
189   for (uint64_t i = 0; i < kIterations; i++) {
190     base::RunLoop run_loop;
191     watcher.Start(pipe.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE,
192                   MOJO_DEADLINE_INDEFINITE,
193                   base::Bind(&OnWatcherSignaled, run_loop.QuitClosure()));
194     ASSERT_TRUE(mojo::test::WriteTextMessage(pipe.handle1.get(), kMessage));
195     run_loop.Run();
196     watcher.Stop();
197 
198     ASSERT_TRUE(
199         mojo::test::ReadTextMessage(pipe.handle0.get(), &received_message));
200     EXPECT_EQ(kMessage, received_message);
201     received_message.clear();
202   }
203 }
204 
205 }  // namespace test
206 }  // namespace common
207 }  // namespace mojo
208