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 <stddef.h>
6 #include <utility>
7
8 #include "base/bind.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/run_loop.h"
11 #include "mojo/public/cpp/bindings/binding.h"
12 #include "mojo/public/cpp/test_support/test_support.h"
13 #include "mojo/public/cpp/test_support/test_utils.h"
14 #include "mojo/public/interfaces/bindings/tests/ping_service.mojom.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16
17 namespace mojo {
18 namespace {
19
20 const double kMojoTicksPerSecond = 1000000.0;
21
MojoTicksToSeconds(MojoTimeTicks ticks)22 double MojoTicksToSeconds(MojoTimeTicks ticks) {
23 return ticks / kMojoTicksPerSecond;
24 }
25
26 class PingServiceImpl : public test::PingService {
27 public:
PingServiceImpl()28 PingServiceImpl() {}
~PingServiceImpl()29 ~PingServiceImpl() override {}
30
31 // |PingService| methods:
32 void Ping(const PingCallback& callback) override;
33
34 private:
35 DISALLOW_COPY_AND_ASSIGN(PingServiceImpl);
36 };
37
Ping(const PingCallback & callback)38 void PingServiceImpl::Ping(const PingCallback& callback) {
39 callback.Run();
40 }
41
42 class PingPongTest {
43 public:
44 explicit PingPongTest(test::PingServicePtr service);
45
46 void Run(unsigned int iterations);
47
48 private:
49 void OnPingDone();
50
51 test::PingServicePtr service_;
52 unsigned int iterations_to_run_;
53 unsigned int current_iterations_;
54
55 base::Closure quit_closure_;
56
57 DISALLOW_COPY_AND_ASSIGN(PingPongTest);
58 };
59
PingPongTest(test::PingServicePtr service)60 PingPongTest::PingPongTest(test::PingServicePtr service)
61 : service_(std::move(service)) {}
62
Run(unsigned int iterations)63 void PingPongTest::Run(unsigned int iterations) {
64 iterations_to_run_ = iterations;
65 current_iterations_ = 0;
66
67 base::RunLoop run_loop;
68 quit_closure_ = run_loop.QuitClosure();
69 service_->Ping(base::Bind(&PingPongTest::OnPingDone, base::Unretained(this)));
70 run_loop.Run();
71 }
72
OnPingDone()73 void PingPongTest::OnPingDone() {
74 current_iterations_++;
75 if (current_iterations_ >= iterations_to_run_) {
76 quit_closure_.Run();
77 return;
78 }
79
80 service_->Ping(base::Bind(&PingPongTest::OnPingDone, base::Unretained(this)));
81 }
82
83 struct BoundPingService {
BoundPingServicemojo::__anonbe7796bc0111::BoundPingService84 BoundPingService() : binding(&impl) {
85 binding.Bind(GetProxy(&service));
86 }
87
88 PingServiceImpl impl;
89 test::PingServicePtr service;
90 Binding<test::PingService> binding;
91 };
92
93 class MojoBindingsPerftest : public testing::Test {
94 public:
MojoBindingsPerftest()95 MojoBindingsPerftest() {}
96
97 protected:
98 base::MessageLoop loop_;
99 };
100
TEST_F(MojoBindingsPerftest,InProcessPingPong)101 TEST_F(MojoBindingsPerftest, InProcessPingPong) {
102 test::PingServicePtr service;
103 PingServiceImpl impl;
104 Binding<test::PingService> binding(&impl, GetProxy(&service));
105 PingPongTest test(std::move(service));
106
107 {
108 const unsigned int kIterations = 100000;
109 const MojoTimeTicks start_time = MojoGetTimeTicksNow();
110 test.Run(kIterations);
111 const MojoTimeTicks end_time = MojoGetTimeTicksNow();
112 test::LogPerfResult(
113 "InProcessPingPong", "0_Inactive",
114 kIterations / MojoTicksToSeconds(end_time - start_time),
115 "pings/second");
116 }
117
118 {
119 const size_t kNumInactiveServices = 1000;
120 BoundPingService* inactive_services =
121 new BoundPingService[kNumInactiveServices];
122
123 const unsigned int kIterations = 10000;
124 const MojoTimeTicks start_time = MojoGetTimeTicksNow();
125 test.Run(kIterations);
126 const MojoTimeTicks end_time = MojoGetTimeTicksNow();
127 test::LogPerfResult(
128 "InProcessPingPong", "1000_Inactive",
129 kIterations / MojoTicksToSeconds(end_time - start_time),
130 "pings/second");
131
132 delete[] inactive_services;
133 }
134 }
135
136 } // namespace
137 } // namespace mojo
138