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 22 double MojoTicksToSeconds(MojoTimeTicks ticks) { 23 return ticks / kMojoTicksPerSecond; 24 } 25 26 class PingServiceImpl : public test::PingService { 27 public: 28 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 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 60 PingPongTest::PingPongTest(test::PingServicePtr service) 61 : service_(std::move(service)) {} 62 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 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 { 84 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: 95 MojoBindingsPerftest() {} 96 97 protected: 98 base::MessageLoop loop_; 99 }; 100 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