blob: 723b96d9ebd38e78f776929c011209c82013f133 [file] [log] [blame]
Yuzhu Shen1a3d5392017-07-18 00:59:341// Copyright 2014 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 <stddef.h>
6#include <memory>
7
Sebastien Marchand6d0558fd2019-01-25 16:49:378#include "base/bind.h"
Yuzhu Shen1a3d5392017-07-18 00:59:349#include "base/memory/ptr_util.h"
Yuzhu Shen1a3d5392017-07-18 00:59:3410#include "base/process/process_metrics.h"
11#include "base/run_loop.h"
12#include "base/strings/stringprintf.h"
13#include "base/synchronization/waitable_event.h"
14#include "base/test/perf_time_logger.h"
Gabriel Charettec7108742019-08-23 03:31:4015#include "base/test/task_environment.h"
yzshen3ec434e2017-07-25 20:26:4316#include "base/threading/thread.h"
Etienne Pierre-dorayc292f862019-06-04 11:00:1817#include "base/threading/thread_task_runner_handle.h"
Yuzhu Shen1a3d5392017-07-18 00:59:3418#include "build/build_config.h"
19#include "ipc/ipc_channel_mojo.h"
Yuzhu Shen4d50dc42017-09-06 20:39:0920#include "ipc/ipc_perftest_messages.h"
21#include "ipc/ipc_perftest_util.h"
Yuzhu Shen1a3d5392017-07-18 00:59:3422#include "ipc/ipc_sync_channel.h"
23#include "ipc/ipc_test.mojom.h"
24#include "ipc/ipc_test_base.h"
Ken Rockot8a7f35f2018-07-04 19:40:5625#include "mojo/core/embedder/embedder.h"
26#include "mojo/core/test/mojo_test_base.h"
27#include "mojo/core/test/multiprocess_test_helper.h"
Julie Jeongeun Kim761a8ff2019-09-27 01:56:4928#include "mojo/public/cpp/bindings/associated_receiver_set.h"
29#include "mojo/public/cpp/bindings/associated_remote.h"
Julie Jeongeun Kim761a8ff2019-09-27 01:56:4930#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
31#include "mojo/public/cpp/bindings/pending_receiver.h"
Julie Jeongeun Kim6eb409ed2019-09-28 01:27:5432#include "mojo/public/cpp/bindings/pending_remote.h"
33#include "mojo/public/cpp/bindings/receiver.h"
Julie Jeongeun Kim761a8ff2019-09-27 01:56:4934#include "mojo/public/cpp/bindings/receiver_set.h"
35#include "mojo/public/cpp/bindings/remote.h"
Yuzhu Shen1a3d5392017-07-18 00:59:3436#include "mojo/public/cpp/system/message_pipe.h"
37
Yuzhu Shen1a3d5392017-07-18 00:59:3438namespace IPC {
39namespace {
40
41class PerformanceChannelListener : public Listener {
42 public:
43 explicit PerformanceChannelListener(const std::string& label)
44 : label_(label),
Lukasz Anforowiczc695e532020-06-09 02:09:4545 sender_(nullptr),
Yuzhu Shen1a3d5392017-07-18 00:59:3446 msg_count_(0),
47 msg_size_(0),
48 sync_(false),
49 count_down_(0) {
50 VLOG(1) << "Server listener up";
51 }
52
53 ~PerformanceChannelListener() override { VLOG(1) << "Server listener down"; }
54
55 void Init(Sender* sender) {
56 DCHECK(!sender_);
57 sender_ = sender;
58 }
59
60 // Call this before running the message loop.
61 void SetTestParams(int msg_count, size_t msg_size, bool sync) {
62 DCHECK_EQ(0, count_down_);
63 msg_count_ = msg_count;
64 msg_size_ = msg_size;
65 sync_ = sync;
66 count_down_ = msg_count_;
67 payload_ = std::string(msg_size_, 'a');
68 }
69
70 bool OnMessageReceived(const Message& message) override {
71 CHECK(sender_);
72
73 bool handled = true;
74 IPC_BEGIN_MESSAGE_MAP(PerformanceChannelListener, message)
75 IPC_MESSAGE_HANDLER(TestMsg_Hello, OnHello)
76 IPC_MESSAGE_HANDLER(TestMsg_Ping, OnPing)
77 IPC_MESSAGE_UNHANDLED(handled = false)
78 IPC_END_MESSAGE_MAP()
79 return handled;
80 }
81
82 void OnHello() {
83 // Start timing on hello.
84 DCHECK(!perf_logger_.get());
85 std::string test_name =
86 base::StringPrintf("IPC_%s_Perf_%dx_%u", label_.c_str(), msg_count_,
87 static_cast<unsigned>(msg_size_));
88 perf_logger_.reset(new base::PerfTimeLogger(test_name.c_str()));
89 if (sync_) {
Yuzhu Shen60efee1a2017-08-08 21:53:4590 for (; count_down_ > 0; --count_down_) {
Yuzhu Shen1a3d5392017-07-18 00:59:3491 std::string response;
92 sender_->Send(new TestMsg_SyncPing(payload_, &response));
93 DCHECK_EQ(response, payload_);
94 }
95 perf_logger_.reset();
Gabriel Charette53a9ef812017-07-26 12:36:2396 base::RunLoop::QuitCurrentWhenIdleDeprecated();
Yuzhu Shen1a3d5392017-07-18 00:59:3497 } else {
98 SendPong();
99 }
100 }
101
102 void OnPing(const std::string& payload) {
103 // Include message deserialization in latency.
104 DCHECK_EQ(payload_.size(), payload.size());
105
106 CHECK(count_down_ > 0);
107 count_down_--;
108 if (count_down_ == 0) {
109 perf_logger_.reset(); // Stop the perf timer now.
Gabriel Charette53a9ef812017-07-26 12:36:23110 base::RunLoop::QuitCurrentWhenIdleDeprecated();
Yuzhu Shen1a3d5392017-07-18 00:59:34111 return;
112 }
113
114 SendPong();
115 }
116
117 void SendPong() { sender_->Send(new TestMsg_Ping(payload_)); }
118
119 private:
120 std::string label_;
121 Sender* sender_;
122 int msg_count_;
123 size_t msg_size_;
124 bool sync_;
125
126 int count_down_;
127 std::string payload_;
128 std::unique_ptr<base::PerfTimeLogger> perf_logger_;
129};
130
Yuzhu Shen1a3d5392017-07-18 00:59:34131class PingPongTestParams {
132 public:
133 PingPongTestParams(size_t size, int count)
134 : message_size_(size), message_count_(count) {}
135
136 size_t message_size() const { return message_size_; }
137 int message_count() const { return message_count_; }
138
139 private:
140 size_t message_size_;
141 int message_count_;
142};
143
Yuzhu Shen60efee1a2017-08-08 21:53:45144class InterfacePassingTestParams {
145 public:
146 InterfacePassingTestParams(size_t rounds, size_t num_interfaces)
147 : rounds_(rounds), num_interfaces_(num_interfaces) {}
148
149 size_t rounds() const { return rounds_; }
150 size_t num_interfaces() const { return num_interfaces_; }
151
152 private:
153 size_t rounds_;
154 size_t num_interfaces_;
155};
156
Yuzhu Shen1a3d5392017-07-18 00:59:34157#ifdef NDEBUG
Yuzhu Shen60efee1a2017-08-08 21:53:45158const int kMultiplier = 100;
Yuzhu Shen1a3d5392017-07-18 00:59:34159#else
160 // Debug builds on Windows run these tests orders of magnitude more slowly.
Yuzhu Shen60efee1a2017-08-08 21:53:45161const int kMultiplier = 1;
Yuzhu Shen1a3d5392017-07-18 00:59:34162#endif
Yuzhu Shen60efee1a2017-08-08 21:53:45163
164std::vector<PingPongTestParams> GetDefaultTestParams() {
165 // Test several sizes. We use 12^N for message size, and limit the message
166 // count to keep the test duration reasonable.
Yuzhu Shen1a3d5392017-07-18 00:59:34167 std::vector<PingPongTestParams> list;
168 list.push_back(PingPongTestParams(12, 500 * kMultiplier));
169 list.push_back(PingPongTestParams(144, 500 * kMultiplier));
170 list.push_back(PingPongTestParams(1728, 500 * kMultiplier));
171 list.push_back(PingPongTestParams(20736, 120 * kMultiplier));
172 list.push_back(PingPongTestParams(248832, 10 * kMultiplier));
173 return list;
174}
175
Yuzhu Shen60efee1a2017-08-08 21:53:45176std::vector<InterfacePassingTestParams> GetDefaultInterfacePassingTestParams() {
177 std::vector<InterfacePassingTestParams> list;
178 list.push_back({500 * kMultiplier, 0});
179 list.push_back({500 * kMultiplier, 1});
180 list.push_back({500 * kMultiplier, 2});
181 list.push_back({500 * kMultiplier, 4});
182 list.push_back({500 * kMultiplier, 8});
183 return list;
184}
185
Yuzhu Shen1a3d5392017-07-18 00:59:34186class MojoChannelPerfTest : public IPCChannelMojoTestBase {
187 public:
188 MojoChannelPerfTest() = default;
189 ~MojoChannelPerfTest() override = default;
190
191 void RunTestChannelProxyPingPong() {
Yuzhu Shen1a3d5392017-07-18 00:59:34192 Init("MojoPerfTestClient");
193
194 // Set up IPC channel and start client.
195 PerformanceChannelListener listener("ChannelProxy");
196 auto channel_proxy = IPC::ChannelProxy::Create(
197 TakeHandle().release(), IPC::Channel::MODE_SERVER, &listener,
Hajime Hoshiff15e972017-11-09 06:37:09198 GetIOThreadTaskRunner(), base::ThreadTaskRunnerHandle::Get());
Yuzhu Shen1a3d5392017-07-18 00:59:34199 listener.Init(channel_proxy.get());
200
201 LockThreadAffinity thread_locker(kSharedCore);
202 std::vector<PingPongTestParams> params = GetDefaultTestParams();
203 for (size_t i = 0; i < params.size(); i++) {
204 listener.SetTestParams(params[i].message_count(),
205 params[i].message_size(), false);
206
207 // This initial message will kick-start the ping-pong of messages.
208 channel_proxy->Send(new TestMsg_Hello);
209
210 // Run message loop.
211 base::RunLoop().Run();
212 }
213
214 // Send quit message.
215 channel_proxy->Send(new TestMsg_Quit);
216
217 EXPECT_TRUE(WaitForClientShutdown());
218 channel_proxy.reset();
Yuzhu Shen1a3d5392017-07-18 00:59:34219 }
220
221 void RunTestChannelProxySyncPing() {
Yuzhu Shen1a3d5392017-07-18 00:59:34222 Init("MojoPerfTestClient");
223
224 // Set up IPC channel and start client.
225 PerformanceChannelListener listener("ChannelProxy");
226 base::WaitableEvent shutdown_event(
227 base::WaitableEvent::ResetPolicy::MANUAL,
228 base::WaitableEvent::InitialState::NOT_SIGNALED);
229 auto channel_proxy = IPC::SyncChannel::Create(
230 TakeHandle().release(), IPC::Channel::MODE_SERVER, &listener,
Hajime Hoshiff15e972017-11-09 06:37:09231 GetIOThreadTaskRunner(), base::ThreadTaskRunnerHandle::Get(), false,
232 &shutdown_event);
Yuzhu Shen1a3d5392017-07-18 00:59:34233 listener.Init(channel_proxy.get());
234
235 LockThreadAffinity thread_locker(kSharedCore);
236 std::vector<PingPongTestParams> params = GetDefaultTestParams();
237 for (size_t i = 0; i < params.size(); i++) {
238 listener.SetTestParams(params[i].message_count(),
239 params[i].message_size(), true);
240
241 // This initial message will kick-start the ping-pong of messages.
242 channel_proxy->Send(new TestMsg_Hello);
243
244 // Run message loop.
245 base::RunLoop().Run();
246 }
247
248 // Send quit message.
249 channel_proxy->Send(new TestMsg_Quit);
250
251 EXPECT_TRUE(WaitForClientShutdown());
252 channel_proxy.reset();
Yuzhu Shen1a3d5392017-07-18 00:59:34253 }
Yuzhu Shen1a3d5392017-07-18 00:59:34254};
255
256TEST_F(MojoChannelPerfTest, ChannelProxyPingPong) {
257 RunTestChannelProxyPingPong();
258
259 base::RunLoop run_loop;
260 run_loop.RunUntilIdle();
261}
262
263TEST_F(MojoChannelPerfTest, ChannelProxySyncPing) {
264 RunTestChannelProxySyncPing();
265
266 base::RunLoop run_loop;
267 run_loop.RunUntilIdle();
268}
269
Yuzhu Shen1a3d5392017-07-18 00:59:34270MULTIPROCESS_TEST_MAIN(MojoPerfTestClientTestChildMain) {
271 MojoPerfTestClient client;
Ken Rockot8a7f35f2018-07-04 19:40:56272 int rv = mojo::core::test::MultiprocessTestHelper::RunClientMain(
Matt Falkenhagenfb888f02019-11-21 00:30:02273 base::BindOnce(&MojoPerfTestClient::Run, base::Unretained(&client)),
Yuzhu Shen1a3d5392017-07-18 00:59:34274 true /* pass_pipe_ownership_to_main */);
275
276 base::RunLoop run_loop;
277 run_loop.RunUntilIdle();
278
279 return rv;
280}
281
Ken Rockot8a7f35f2018-07-04 19:40:56282class MojoInterfacePerfTest : public mojo::core::test::MojoTestBase {
Yuzhu Shen1a3d5392017-07-18 00:59:34283 public:
284 MojoInterfacePerfTest() : message_count_(0), count_down_(0) {}
285
286 protected:
287 void RunPingPongServer(MojoHandle mp, const std::string& label) {
288 label_ = label;
289
290 mojo::MessagePipeHandle mp_handle(mp);
291 mojo::ScopedMessagePipeHandle scoped_mp(mp_handle);
Julie Jeongeun Kim6eb409ed2019-09-28 01:27:54292 ping_receiver_.Bind(
293 mojo::PendingRemote<IPC::mojom::Reflector>(std::move(scoped_mp), 0u));
Yuzhu Shen1a3d5392017-07-18 00:59:34294
295 LockThreadAffinity thread_locker(kSharedCore);
296 std::vector<PingPongTestParams> params = GetDefaultTestParams();
297 for (size_t i = 0; i < params.size(); i++) {
Matt Falkenhagenfb888f02019-11-21 00:30:02298 ping_receiver_->Ping("hello",
299 base::BindOnce(&MojoInterfacePerfTest::OnPong,
300 base::Unretained(this)));
Yuzhu Shen1a3d5392017-07-18 00:59:34301 message_count_ = count_down_ = params[i].message_count();
302 payload_ = std::string(params[i].message_size(), 'a');
303
304 base::RunLoop().Run();
305 }
306
307 ping_receiver_->Quit();
308
Julie Jeongeun Kim6eb409ed2019-09-28 01:27:54309 ignore_result(ping_receiver_.Unbind().PassPipe().release());
Yuzhu Shen1a3d5392017-07-18 00:59:34310 }
311
312 void OnPong(const std::string& value) {
313 if (value == "hello") {
314 DCHECK(!perf_logger_.get());
315 std::string test_name =
316 base::StringPrintf("IPC_%s_Perf_%dx_%zu", label_.c_str(),
317 message_count_, payload_.size());
318 perf_logger_.reset(new base::PerfTimeLogger(test_name.c_str()));
319 } else {
320 DCHECK_EQ(payload_.size(), value.size());
321
322 CHECK(count_down_ > 0);
323 count_down_--;
324 if (count_down_ == 0) {
325 perf_logger_.reset();
Gabriel Charette53a9ef812017-07-26 12:36:23326 base::RunLoop::QuitCurrentWhenIdleDeprecated();
Yuzhu Shen1a3d5392017-07-18 00:59:34327 return;
328 }
329 }
330
331 if (sync_) {
332 for (int i = 0; i < count_down_; ++i) {
333 std::string response;
334 ping_receiver_->SyncPing(payload_, &response);
335 DCHECK_EQ(response, payload_);
336 }
337 perf_logger_.reset();
Gabriel Charette53a9ef812017-07-26 12:36:23338 base::RunLoop::QuitCurrentWhenIdleDeprecated();
Yuzhu Shen1a3d5392017-07-18 00:59:34339 } else {
Matt Falkenhagenfb888f02019-11-21 00:30:02340 ping_receiver_->Ping(payload_,
341 base::BindOnce(&MojoInterfacePerfTest::OnPong,
342 base::Unretained(this)));
Yuzhu Shen1a3d5392017-07-18 00:59:34343 }
344 }
345
346 static int RunPingPongClient(MojoHandle mp) {
347 mojo::MessagePipeHandle mp_handle(mp);
348 mojo::ScopedMessagePipeHandle scoped_mp(mp_handle);
349
Gabriel Charette43b8bf32017-11-08 20:24:43350 LockThreadAffinity thread_locker(kSharedCore);
Yuzhu Shen1a3d5392017-07-18 00:59:34351 // In single process mode, this is running in a task and by default other
352 // tasks (in particular, the binding) won't run. To keep the single process
353 // and multi-process code paths the same, enable nestable tasks.
Gabriel Charette43b8bf32017-11-08 20:24:43354 base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed);
Yuzhu Shen4d50dc42017-09-06 20:39:09355 ReflectorImpl impl(std::move(scoped_mp), run_loop.QuitWhenIdleClosure());
356 run_loop.Run();
Yuzhu Shen1a3d5392017-07-18 00:59:34357 return 0;
358 }
359
360 bool sync_ = false;
361
362 private:
363 int message_count_;
364 int count_down_;
365 std::string label_;
366 std::string payload_;
Julie Jeongeun Kim6eb409ed2019-09-28 01:27:54367 mojo::Remote<IPC::mojom::Reflector> ping_receiver_;
Yuzhu Shen1a3d5392017-07-18 00:59:34368 std::unique_ptr<base::PerfTimeLogger> perf_logger_;
369
370 DISALLOW_COPY_AND_ASSIGN(MojoInterfacePerfTest);
371};
372
Yuzhu Shen60efee1a2017-08-08 21:53:45373class InterfacePassingTestDriverImpl : public mojom::InterfacePassingTestDriver,
374 public mojom::PingReceiver {
375 public:
376 InterfacePassingTestDriverImpl(mojo::ScopedMessagePipeHandle handle,
377 const base::Closure& quit_closure)
Julie Jeongeun Kim6eb409ed2019-09-28 01:27:54378 : receiver_(this,
379 mojo::PendingReceiver<mojom::InterfacePassingTestDriver>(
380 std::move(handle))),
Yuzhu Shen60efee1a2017-08-08 21:53:45381 quit_closure_(quit_closure) {}
382 ~InterfacePassingTestDriverImpl() override {
Julie Jeongeun Kim6eb409ed2019-09-28 01:27:54383 ignore_result(receiver_.Unbind().PassPipe().release());
Yuzhu Shen60efee1a2017-08-08 21:53:45384 }
385
386 private:
387 // mojom::InterfacePassingTestDriver implementation:
388 void Init(InitCallback callback) override { std::move(callback).Run(); }
389
Julie Jeongeun Kim761a8ff2019-09-27 01:56:49390 void GetPingReceiver(
391 std::vector<mojo::PendingReceiver<mojom::PingReceiver>> receivers,
392 GetPingReceiverCallback callback) override {
393 for (auto& receiver : receivers)
394 ping_receiver_receivers_.Add(this, std::move(receiver));
395 ping_receiver_receivers_.Clear();
Yuzhu Shen60efee1a2017-08-08 21:53:45396 std::move(callback).Run();
397 }
398
399 void GetAssociatedPingReceiver(
Julie Jeongeun Kim761a8ff2019-09-27 01:56:49400 std::vector<mojo::PendingAssociatedReceiver<mojom::PingReceiver>>
401 receivers,
Yuzhu Shen60efee1a2017-08-08 21:53:45402 GetAssociatedPingReceiverCallback callback) override {
Julie Jeongeun Kim761a8ff2019-09-27 01:56:49403 for (auto& receiver : receivers)
404 ping_receiver_associated_receivers_.Add(this, std::move(receiver));
405 ping_receiver_associated_receivers_.Clear();
Yuzhu Shen60efee1a2017-08-08 21:53:45406 std::move(callback).Run();
407 }
408
409 void Quit() override {
410 if (quit_closure_)
411 quit_closure_.Run();
412 }
413
414 // mojom::PingReceiver implementation:
415 void Ping(PingCallback callback) override { std::move(callback).Run(); }
416
Julie Jeongeun Kim761a8ff2019-09-27 01:56:49417 mojo::ReceiverSet<mojom::PingReceiver> ping_receiver_receivers_;
418 mojo::AssociatedReceiverSet<mojom::PingReceiver>
419 ping_receiver_associated_receivers_;
Julie Jeongeun Kim6eb409ed2019-09-28 01:27:54420 mojo::Receiver<mojom::InterfacePassingTestDriver> receiver_;
Yuzhu Shen60efee1a2017-08-08 21:53:45421
422 base::Closure quit_closure_;
423};
424
Ken Rockot8a7f35f2018-07-04 19:40:56425class MojoInterfacePassingPerfTest : public mojo::core::test::MojoTestBase {
Yuzhu Shen60efee1a2017-08-08 21:53:45426 public:
427 MojoInterfacePassingPerfTest() = default;
428
429 protected:
430 void RunInterfacePassingServer(MojoHandle mp,
431 const std::string& label,
432 bool associated) {
433 label_ = label;
434 associated_ = associated;
435
436 mojo::MessagePipeHandle mp_handle(mp);
437 mojo::ScopedMessagePipeHandle scoped_mp(mp_handle);
Julie Jeongeun Kim6eb409ed2019-09-28 01:27:54438 driver_remote_.Bind(mojo::PendingRemote<mojom::InterfacePassingTestDriver>(
439 std::move(scoped_mp), 0u));
Yuzhu Shen60efee1a2017-08-08 21:53:45440
441 auto params = GetDefaultInterfacePassingTestParams();
442
443 LockThreadAffinity thread_locker(kSharedCore);
444 for (size_t i = 0; i < params.size(); ++i) {
Julie Jeongeun Kim6eb409ed2019-09-28 01:27:54445 driver_remote_->Init(
Matt Falkenhagenfb888f02019-11-21 00:30:02446 base::BindOnce(&MojoInterfacePassingPerfTest::OnInitCallback,
447 base::Unretained(this)));
Yuzhu Shen60efee1a2017-08-08 21:53:45448 rounds_ = count_down_ = params[i].rounds();
449 num_interfaces_ = params[i].num_interfaces();
450
451 base::RunLoop run_loop;
452 quit_closure_ = run_loop.QuitWhenIdleClosure();
453 run_loop.Run();
454 }
455
Julie Jeongeun Kim6eb409ed2019-09-28 01:27:54456 driver_remote_->Quit();
Yuzhu Shen60efee1a2017-08-08 21:53:45457
Julie Jeongeun Kim6eb409ed2019-09-28 01:27:54458 ignore_result(driver_remote_.Unbind().PassPipe().release());
Yuzhu Shen60efee1a2017-08-08 21:53:45459 }
460
461 void OnInitCallback() {
462 DCHECK(!perf_logger_.get());
463 std::string test_name = base::StringPrintf(
464 "IPC_%s_Perf_%zux_%zu", label_.c_str(), rounds_, num_interfaces_);
465 perf_logger_.reset(new base::PerfTimeLogger(test_name.c_str()));
466
467 DoNextRound();
468 }
469
470 void DoNextRound() {
471 if (associated_) {
Julie Jeongeun Kim761a8ff2019-09-27 01:56:49472 std::vector<mojo::AssociatedRemote<mojom::PingReceiver>>
473 associated_remotes(num_interfaces_);
Yuzhu Shen60efee1a2017-08-08 21:53:45474
Julie Jeongeun Kim761a8ff2019-09-27 01:56:49475 std::vector<mojo::PendingAssociatedReceiver<mojom::PingReceiver>>
476 receivers(num_interfaces_);
Yuzhu Shen60efee1a2017-08-08 21:53:45477 for (size_t i = 0; i < num_interfaces_; ++i) {
Julie Jeongeun Kim761a8ff2019-09-27 01:56:49478 receivers[i] = associated_remotes[i].BindNewEndpointAndPassReceiver();
Yuzhu Shen60efee1a2017-08-08 21:53:45479 // Force the interface pointer to do full initialization.
Julie Jeongeun Kim761a8ff2019-09-27 01:56:49480 associated_remotes[i].get();
Yuzhu Shen60efee1a2017-08-08 21:53:45481 }
482
Julie Jeongeun Kim6eb409ed2019-09-28 01:27:54483 driver_remote_->GetAssociatedPingReceiver(
Julie Jeongeun Kim761a8ff2019-09-27 01:56:49484 std::move(receivers),
Matt Falkenhagenfb888f02019-11-21 00:30:02485 base::BindOnce(&MojoInterfacePassingPerfTest::OnGetReceiverCallback,
486 base::Unretained(this)));
Yuzhu Shen60efee1a2017-08-08 21:53:45487 } else {
Julie Jeongeun Kim761a8ff2019-09-27 01:56:49488 std::vector<mojo::Remote<mojom::PingReceiver>> remotes(num_interfaces_);
Yuzhu Shen60efee1a2017-08-08 21:53:45489
Julie Jeongeun Kim761a8ff2019-09-27 01:56:49490 std::vector<mojo::PendingReceiver<mojom::PingReceiver>> receivers(
491 num_interfaces_);
Yuzhu Shen60efee1a2017-08-08 21:53:45492 for (size_t i = 0; i < num_interfaces_; ++i) {
Julie Jeongeun Kim761a8ff2019-09-27 01:56:49493 receivers[i] = remotes[i].BindNewPipeAndPassReceiver();
Yuzhu Shen60efee1a2017-08-08 21:53:45494 // Force the interface pointer to do full initialization.
Julie Jeongeun Kim761a8ff2019-09-27 01:56:49495 remotes[i].get();
Yuzhu Shen60efee1a2017-08-08 21:53:45496 }
497
Julie Jeongeun Kim6eb409ed2019-09-28 01:27:54498 driver_remote_->GetPingReceiver(
Julie Jeongeun Kim761a8ff2019-09-27 01:56:49499 std::move(receivers),
Matt Falkenhagenfb888f02019-11-21 00:30:02500 base::BindOnce(&MojoInterfacePassingPerfTest::OnGetReceiverCallback,
501 base::Unretained(this)));
Yuzhu Shen60efee1a2017-08-08 21:53:45502 }
503 }
504
505 void OnGetReceiverCallback() {
506 CHECK_GT(count_down_, 0u);
507 count_down_--;
508
509 if (count_down_ == 0) {
510 perf_logger_.reset();
511 quit_closure_.Run();
512 return;
513 }
514
515 DoNextRound();
516 }
517
518 static int RunInterfacePassingClient(MojoHandle mp) {
519 mojo::MessagePipeHandle mp_handle(mp);
520 mojo::ScopedMessagePipeHandle scoped_mp(mp_handle);
521
Gabriel Charette43b8bf32017-11-08 20:24:43522 LockThreadAffinity thread_locker(kSharedCore);
Yuzhu Shen60efee1a2017-08-08 21:53:45523 // In single process mode, this is running in a task and by default other
524 // tasks (in particular, the binding) won't run. To keep the single process
525 // and multi-process code paths the same, enable nestable tasks.
Gabriel Charette43b8bf32017-11-08 20:24:43526 base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed);
Yuzhu Shen60efee1a2017-08-08 21:53:45527 InterfacePassingTestDriverImpl impl(std::move(scoped_mp),
528 run_loop.QuitWhenIdleClosure());
529 run_loop.Run();
530 return 0;
531 }
532
533 private:
534 size_t rounds_ = 0;
535 size_t count_down_ = 0;
536 size_t num_interfaces_ = 0;
537 std::string label_;
538 bool associated_ = false;
539 std::unique_ptr<base::PerfTimeLogger> perf_logger_;
540
Julie Jeongeun Kim6eb409ed2019-09-28 01:27:54541 mojo::Remote<mojom::InterfacePassingTestDriver> driver_remote_;
Yuzhu Shen60efee1a2017-08-08 21:53:45542
543 base::Closure quit_closure_;
544
545 DISALLOW_COPY_AND_ASSIGN(MojoInterfacePassingPerfTest);
546};
547
548DEFINE_TEST_CLIENT_WITH_PIPE(InterfacePassingClient,
549 MojoInterfacePassingPerfTest,
550 h) {
Gabriel Charettec523fa62019-09-09 23:03:32551 base::test::SingleThreadTaskEnvironment task_environment;
Yuzhu Shen60efee1a2017-08-08 21:53:45552 return RunInterfacePassingClient(h);
553}
554
Yuzhu Shen1a3d5392017-07-18 00:59:34555enum class InProcessMessageMode {
556 kSerialized,
557 kUnserialized,
558};
559
Yuzhu Shen60efee1a2017-08-08 21:53:45560template <class TestBase>
561class InProcessPerfTest
562 : public TestBase,
Yuzhu Shen1a3d5392017-07-18 00:59:34563 public testing::WithParamInterface<InProcessMessageMode> {
564 public:
Yuzhu Shen60efee1a2017-08-08 21:53:45565 InProcessPerfTest() {
Yuzhu Shen1a3d5392017-07-18 00:59:34566 switch (GetParam()) {
567 case InProcessMessageMode::kSerialized:
568 mojo::Connector::OverrideDefaultSerializationBehaviorForTesting(
569 mojo::Connector::OutgoingSerializationMode::kEager,
570 mojo::Connector::IncomingSerializationMode::kDispatchAsIs);
571 break;
572 case InProcessMessageMode::kUnserialized:
573 mojo::Connector::OverrideDefaultSerializationBehaviorForTesting(
574 mojo::Connector::OutgoingSerializationMode::kLazy,
575 mojo::Connector::IncomingSerializationMode::kDispatchAsIs);
576 break;
577 }
578 }
579};
580
Yuzhu Shen60efee1a2017-08-08 21:53:45581using MojoInProcessInterfacePerfTest = InProcessPerfTest<MojoInterfacePerfTest>;
582using MojoInProcessInterfacePassingPerfTest =
583 InProcessPerfTest<MojoInterfacePassingPerfTest>;
584
Yuzhu Shen1a3d5392017-07-18 00:59:34585DEFINE_TEST_CLIENT_WITH_PIPE(PingPongClient, MojoInterfacePerfTest, h) {
Gabriel Charettec523fa62019-09-09 23:03:32586 base::test::SingleThreadTaskEnvironment task_environment;
Yuzhu Shen1a3d5392017-07-18 00:59:34587 return RunPingPongClient(h);
588}
589
590// Similar to MojoChannelPerfTest above, but uses a Mojo interface instead of
591// raw IPC::Messages.
592TEST_F(MojoInterfacePerfTest, MultiprocessPingPong) {
593 RunTestClient("PingPongClient", [&](MojoHandle h) {
Gabriel Charettec523fa62019-09-09 23:03:32594 base::test::SingleThreadTaskEnvironment task_environment;
Yuzhu Shen1a3d5392017-07-18 00:59:34595 RunPingPongServer(h, "Multiprocess");
596 });
597}
598
599TEST_F(MojoInterfacePerfTest, MultiprocessSyncPing) {
600 sync_ = true;
601 RunTestClient("PingPongClient", [&](MojoHandle h) {
Gabriel Charettec523fa62019-09-09 23:03:32602 base::test::SingleThreadTaskEnvironment task_environment;
Yuzhu Shen1a3d5392017-07-18 00:59:34603 RunPingPongServer(h, "MultiprocessSync");
604 });
605}
606
Yuzhu Shen60efee1a2017-08-08 21:53:45607TEST_F(MojoInterfacePassingPerfTest, MultiprocessInterfacePassing) {
608 RunTestClient("InterfacePassingClient", [&](MojoHandle h) {
Gabriel Charettec523fa62019-09-09 23:03:32609 base::test::SingleThreadTaskEnvironment task_environment;
Yuzhu Shen60efee1a2017-08-08 21:53:45610 RunInterfacePassingServer(h, "InterfacePassing", false /* associated */);
611 });
612}
613
614TEST_F(MojoInterfacePassingPerfTest, MultiprocessAssociatedInterfacePassing) {
615 RunTestClient("InterfacePassingClient", [&](MojoHandle h) {
Gabriel Charettec523fa62019-09-09 23:03:32616 base::test::SingleThreadTaskEnvironment task_environment;
Yuzhu Shen60efee1a2017-08-08 21:53:45617 RunInterfacePassingServer(h, "AssociatedInterfacePassing",
618 true /* associated*/);
619 });
620}
621
Yuzhu Shen1a3d5392017-07-18 00:59:34622// A single process version of the above test.
623TEST_P(MojoInProcessInterfacePerfTest, MultiThreadPingPong) {
624 MojoHandle server_handle, client_handle;
625 CreateMessagePipe(&server_handle, &client_handle);
626
627 base::Thread client_thread("PingPongClient");
628 client_thread.Start();
629 client_thread.task_runner()->PostTask(
630 FROM_HERE,
kylecharf448cc92019-02-19 20:28:09631 base::BindOnce(base::IgnoreResult(&RunPingPongClient), client_handle));
Yuzhu Shen1a3d5392017-07-18 00:59:34632
Gabriel Charettec523fa62019-09-09 23:03:32633 base::test::SingleThreadTaskEnvironment task_environment;
Yuzhu Shen1a3d5392017-07-18 00:59:34634 RunPingPongServer(server_handle, "SingleProcess");
635}
636
637TEST_P(MojoInProcessInterfacePerfTest, SingleThreadPingPong) {
638 MojoHandle server_handle, client_handle;
639 CreateMessagePipe(&server_handle, &client_handle);
640
Gabriel Charettec523fa62019-09-09 23:03:32641 base::test::SingleThreadTaskEnvironment task_environment;
Yuzhu Shen1a3d5392017-07-18 00:59:34642 mojo::MessagePipeHandle mp_handle(client_handle);
643 mojo::ScopedMessagePipeHandle scoped_mp(mp_handle);
644 LockThreadAffinity thread_locker(kSharedCore);
Yuzhu Shen4d50dc42017-09-06 20:39:09645 ReflectorImpl impl(std::move(scoped_mp), base::Closure());
Yuzhu Shen1a3d5392017-07-18 00:59:34646
647 RunPingPongServer(server_handle, "SingleProcess");
648}
649
Ilia Samsonovf2a4ade2019-11-21 22:51:38650INSTANTIATE_TEST_SUITE_P(All,
Victor Costan8184ed42019-01-28 18:26:45651 MojoInProcessInterfacePerfTest,
652 testing::Values(InProcessMessageMode::kSerialized,
653 InProcessMessageMode::kUnserialized));
Yuzhu Shen1a3d5392017-07-18 00:59:34654
Yuzhu Shen60efee1a2017-08-08 21:53:45655TEST_P(MojoInProcessInterfacePassingPerfTest, MultiThreadInterfacePassing) {
656 MojoHandle server_handle, client_handle;
657 CreateMessagePipe(&server_handle, &client_handle);
658
659 base::Thread client_thread("InterfacePassingClient");
660 client_thread.Start();
661 client_thread.task_runner()->PostTask(
kylecharf448cc92019-02-19 20:28:09662 FROM_HERE, base::BindOnce(base::IgnoreResult(&RunInterfacePassingClient),
663 client_handle));
Yuzhu Shen60efee1a2017-08-08 21:53:45664
Gabriel Charettec523fa62019-09-09 23:03:32665 base::test::SingleThreadTaskEnvironment task_environment;
Yuzhu Shen60efee1a2017-08-08 21:53:45666 RunInterfacePassingServer(server_handle, "SingleProcess",
667 false /* associated */);
668}
669
670TEST_P(MojoInProcessInterfacePassingPerfTest,
671 MultiThreadAssociatedInterfacePassing) {
672 MojoHandle server_handle, client_handle;
673 CreateMessagePipe(&server_handle, &client_handle);
674
675 base::Thread client_thread("InterfacePassingClient");
676 client_thread.Start();
677 client_thread.task_runner()->PostTask(
kylecharf448cc92019-02-19 20:28:09678 FROM_HERE, base::BindOnce(base::IgnoreResult(&RunInterfacePassingClient),
679 client_handle));
Yuzhu Shen60efee1a2017-08-08 21:53:45680
Gabriel Charettec523fa62019-09-09 23:03:32681 base::test::SingleThreadTaskEnvironment task_environment;
Yuzhu Shen60efee1a2017-08-08 21:53:45682 RunInterfacePassingServer(server_handle, "SingleProcess",
683 true /* associated */);
684}
685
686TEST_P(MojoInProcessInterfacePassingPerfTest, SingleThreadInterfacePassing) {
687 MojoHandle server_handle, client_handle;
688 CreateMessagePipe(&server_handle, &client_handle);
689
Gabriel Charettec523fa62019-09-09 23:03:32690 base::test::SingleThreadTaskEnvironment task_environment;
Yuzhu Shen60efee1a2017-08-08 21:53:45691 mojo::MessagePipeHandle mp_handle(client_handle);
692 mojo::ScopedMessagePipeHandle scoped_mp(mp_handle);
693 LockThreadAffinity thread_locker(kSharedCore);
694 InterfacePassingTestDriverImpl impl(std::move(scoped_mp), base::Closure());
695
696 RunInterfacePassingServer(server_handle, "SingleProcess",
697 false /* associated */);
698}
699
700TEST_P(MojoInProcessInterfacePassingPerfTest,
701 SingleThreadAssociatedInterfacePassing) {
702 MojoHandle server_handle, client_handle;
703 CreateMessagePipe(&server_handle, &client_handle);
704
Gabriel Charettec523fa62019-09-09 23:03:32705 base::test::SingleThreadTaskEnvironment task_environment;
Yuzhu Shen60efee1a2017-08-08 21:53:45706 mojo::MessagePipeHandle mp_handle(client_handle);
707 mojo::ScopedMessagePipeHandle scoped_mp(mp_handle);
708 LockThreadAffinity thread_locker(kSharedCore);
709 InterfacePassingTestDriverImpl impl(std::move(scoped_mp), base::Closure());
710
711 RunInterfacePassingServer(server_handle, "SingleProcess",
712 true /* associated */);
713}
714
Ilia Samsonovf2a4ade2019-11-21 22:51:38715INSTANTIATE_TEST_SUITE_P(All,
Victor Costan8184ed42019-01-28 18:26:45716 MojoInProcessInterfacePassingPerfTest,
717 testing::Values(InProcessMessageMode::kSerialized,
718 InProcessMessageMode::kUnserialized));
Yuzhu Shen60efee1a2017-08-08 21:53:45719
Yuzhu Shen1a3d5392017-07-18 00:59:34720class CallbackPerfTest : public testing::Test {
721 public:
722 CallbackPerfTest()
723 : client_thread_("PingPongClient"), message_count_(0), count_down_(0) {}
724
725 protected:
726 void RunMultiThreadPingPongServer() {
727 client_thread_.Start();
728
729 LockThreadAffinity thread_locker(kSharedCore);
730 std::vector<PingPongTestParams> params = GetDefaultTestParams();
731 for (size_t i = 0; i < params.size(); i++) {
732 std::string hello("hello");
733 client_thread_.task_runner()->PostTask(
kylecharf448cc92019-02-19 20:28:09734 FROM_HERE, base::BindOnce(&CallbackPerfTest::Ping,
735 base::Unretained(this), hello));
Yuzhu Shen1a3d5392017-07-18 00:59:34736 message_count_ = count_down_ = params[i].message_count();
737 payload_ = std::string(params[i].message_size(), 'a');
738
739 base::RunLoop().Run();
740 }
741 }
742
743 void Ping(const std::string& value) {
Gabriel Charettedfa36042019-08-19 17:30:11744 task_environment_.GetMainThreadTaskRunner()->PostTask(
kylecharf448cc92019-02-19 20:28:09745 FROM_HERE, base::BindOnce(&CallbackPerfTest::OnPong,
746 base::Unretained(this), value));
Yuzhu Shen1a3d5392017-07-18 00:59:34747 }
748
749 void OnPong(const std::string& value) {
750 if (value == "hello") {
751 DCHECK(!perf_logger_.get());
752 std::string test_name =
753 base::StringPrintf("Callback_MultiProcess_Perf_%dx_%zu",
754 message_count_, payload_.size());
755 perf_logger_.reset(new base::PerfTimeLogger(test_name.c_str()));
756 } else {
757 DCHECK_EQ(payload_.size(), value.size());
758
759 CHECK(count_down_ > 0);
760 count_down_--;
761 if (count_down_ == 0) {
762 perf_logger_.reset();
Gabriel Charette53a9ef812017-07-26 12:36:23763 base::RunLoop::QuitCurrentWhenIdleDeprecated();
Yuzhu Shen1a3d5392017-07-18 00:59:34764 return;
765 }
766 }
767
768 client_thread_.task_runner()->PostTask(
kylecharf448cc92019-02-19 20:28:09769 FROM_HERE, base::BindOnce(&CallbackPerfTest::Ping,
770 base::Unretained(this), payload_));
Yuzhu Shen1a3d5392017-07-18 00:59:34771 }
772
773 void RunSingleThreadNoPostTaskPingPongServer() {
774 LockThreadAffinity thread_locker(kSharedCore);
775 std::vector<PingPongTestParams> params = GetDefaultTestParams();
Matt Falkenhagenfb888f02019-11-21 00:30:02776 base::RepeatingCallback<void(
777 const std::string&, int,
778 base::OnceCallback<void(const std::string&, int)>)>
779 ping =
780 base::BindRepeating(&CallbackPerfTest::SingleThreadPingNoPostTask,
781 base::Unretained(this));
Yuzhu Shen1a3d5392017-07-18 00:59:34782 for (size_t i = 0; i < params.size(); i++) {
783 payload_ = std::string(params[i].message_size(), 'a');
784 std::string test_name =
Vladislav Kuzkokov651c81f2017-10-27 13:31:41785 base::StringPrintf("Callback_SingleThreadNoPostTask_Perf_%dx_%zu",
Yuzhu Shen1a3d5392017-07-18 00:59:34786 params[i].message_count(), payload_.size());
787 perf_logger_.reset(new base::PerfTimeLogger(test_name.c_str()));
788 for (int j = 0; j < params[i].message_count(); ++j) {
Vladislav Kuzkokov651c81f2017-10-27 13:31:41789 ping.Run(payload_, j,
Matt Falkenhagenfb888f02019-11-21 00:30:02790 base::BindOnce(&CallbackPerfTest::SingleThreadPongNoPostTask,
791 base::Unretained(this)));
Yuzhu Shen1a3d5392017-07-18 00:59:34792 }
793 perf_logger_.reset();
794 }
795 }
796
797 void SingleThreadPingNoPostTask(
798 const std::string& value,
Vladislav Kuzkokov651c81f2017-10-27 13:31:41799 int i,
Matt Falkenhagenfb888f02019-11-21 00:30:02800 base::OnceCallback<void(const std::string&, int)> pong) {
801 std::move(pong).Run(value, i);
Yuzhu Shen1a3d5392017-07-18 00:59:34802 }
803
Vladislav Kuzkokov651c81f2017-10-27 13:31:41804 void SingleThreadPongNoPostTask(const std::string& value, int i) {}
Yuzhu Shen1a3d5392017-07-18 00:59:34805
806 void RunSingleThreadPostTaskPingPongServer() {
807 LockThreadAffinity thread_locker(kSharedCore);
808 std::vector<PingPongTestParams> params = GetDefaultTestParams();
809 for (size_t i = 0; i < params.size(); i++) {
810 std::string hello("hello");
Etienne Pierre-dorayc292f862019-06-04 11:00:18811 base::ThreadTaskRunnerHandle::Get()->PostTask(
kylecharf448cc92019-02-19 20:28:09812 FROM_HERE, base::BindOnce(&CallbackPerfTest::SingleThreadPingPostTask,
813 base::Unretained(this), hello));
Yuzhu Shen1a3d5392017-07-18 00:59:34814 message_count_ = count_down_ = params[i].message_count();
815 payload_ = std::string(params[i].message_size(), 'a');
816
817 base::RunLoop().Run();
818 }
819 }
820
821 void SingleThreadPingPostTask(const std::string& value) {
Etienne Pierre-dorayc292f862019-06-04 11:00:18822 base::ThreadTaskRunnerHandle::Get()->PostTask(
kylecharf448cc92019-02-19 20:28:09823 FROM_HERE, base::BindOnce(&CallbackPerfTest::SingleThreadPongPostTask,
824 base::Unretained(this), value));
Yuzhu Shen1a3d5392017-07-18 00:59:34825 }
826
827 void SingleThreadPongPostTask(const std::string& value) {
828 if (value == "hello") {
829 DCHECK(!perf_logger_.get());
830 std::string test_name =
Vladislav Kuzkokov651c81f2017-10-27 13:31:41831 base::StringPrintf("Callback_SingleThreadPostTask_Perf_%dx_%zu",
Yuzhu Shen1a3d5392017-07-18 00:59:34832 message_count_, payload_.size());
833 perf_logger_.reset(new base::PerfTimeLogger(test_name.c_str()));
834 } else {
835 DCHECK_EQ(payload_.size(), value.size());
836
837 CHECK(count_down_ > 0);
838 count_down_--;
839 if (count_down_ == 0) {
840 perf_logger_.reset();
Gabriel Charette53a9ef812017-07-26 12:36:23841 base::RunLoop::QuitCurrentWhenIdleDeprecated();
Yuzhu Shen1a3d5392017-07-18 00:59:34842 return;
843 }
844 }
845
Etienne Pierre-dorayc292f862019-06-04 11:00:18846 base::ThreadTaskRunnerHandle::Get()->PostTask(
kylecharf448cc92019-02-19 20:28:09847 FROM_HERE, base::BindOnce(&CallbackPerfTest::SingleThreadPingPostTask,
848 base::Unretained(this), payload_));
Yuzhu Shen1a3d5392017-07-18 00:59:34849 }
850
851 private:
852 base::Thread client_thread_;
Gabriel Charettec523fa62019-09-09 23:03:32853 base::test::SingleThreadTaskEnvironment task_environment_;
Yuzhu Shen1a3d5392017-07-18 00:59:34854 int message_count_;
855 int count_down_;
856 std::string payload_;
857 std::unique_ptr<base::PerfTimeLogger> perf_logger_;
858
859 DISALLOW_COPY_AND_ASSIGN(CallbackPerfTest);
860};
861
862// Sends the same data as above using PostTask to a different thread instead of
863// IPCs for comparison.
864TEST_F(CallbackPerfTest, MultiThreadPingPong) {
865 RunMultiThreadPingPongServer();
866}
867
868// Sends the same data as above using PostTask to the same thread.
869TEST_F(CallbackPerfTest, SingleThreadPostTaskPingPong) {
870 RunSingleThreadPostTaskPingPongServer();
871}
872
873// Sends the same data as above without using PostTask to the same thread.
874TEST_F(CallbackPerfTest, SingleThreadNoPostTaskPingPong) {
875 RunSingleThreadNoPostTaskPingPongServer();
876}
877
878} // namespace
879} // namespace IPC