ipc_mojo_perftest.cc 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890
  1. // 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. #include <stddef.h>
  5. #include <memory>
  6. #include <tuple>
  7. #include "base/bind.h"
  8. #include "base/callback.h"
  9. #include "base/memory/ptr_util.h"
  10. #include "base/memory/raw_ptr.h"
  11. #include "base/process/process_metrics.h"
  12. #include "base/run_loop.h"
  13. #include "base/strings/stringprintf.h"
  14. #include "base/synchronization/waitable_event.h"
  15. #include "base/test/perf_time_logger.h"
  16. #include "base/test/task_environment.h"
  17. #include "base/threading/thread.h"
  18. #include "base/threading/thread_task_runner_handle.h"
  19. #include "base/time/time.h"
  20. #include "build/build_config.h"
  21. #include "ipc/ipc_channel_mojo.h"
  22. #include "ipc/ipc_perftest_messages.h"
  23. #include "ipc/ipc_perftest_util.h"
  24. #include "ipc/ipc_sync_channel.h"
  25. #include "ipc/ipc_test.mojom.h"
  26. #include "ipc/ipc_test_base.h"
  27. #include "mojo/core/embedder/embedder.h"
  28. #include "mojo/core/test/mojo_test_base.h"
  29. #include "mojo/core/test/multiprocess_test_helper.h"
  30. #include "mojo/public/cpp/bindings/associated_receiver_set.h"
  31. #include "mojo/public/cpp/bindings/associated_remote.h"
  32. #include "mojo/public/cpp/bindings/pending_associated_receiver.h"
  33. #include "mojo/public/cpp/bindings/pending_receiver.h"
  34. #include "mojo/public/cpp/bindings/pending_remote.h"
  35. #include "mojo/public/cpp/bindings/receiver.h"
  36. #include "mojo/public/cpp/bindings/receiver_set.h"
  37. #include "mojo/public/cpp/bindings/remote.h"
  38. #include "mojo/public/cpp/system/message_pipe.h"
  39. namespace IPC {
  40. namespace {
  41. class PerformanceChannelListener : public Listener {
  42. public:
  43. explicit PerformanceChannelListener(const std::string& label)
  44. : label_(label),
  45. sender_(nullptr),
  46. msg_count_(0),
  47. msg_size_(0),
  48. sync_(false),
  49. count_down_(0) {
  50. VLOG(1) << "Server listener up";
  51. }
  52. ~PerformanceChannelListener() override { VLOG(1) << "Server listener down"; }
  53. void Init(Sender* sender) {
  54. DCHECK(!sender_);
  55. sender_ = sender;
  56. }
  57. // Call this before running the message loop.
  58. void SetTestParams(int msg_count, size_t msg_size, bool sync) {
  59. DCHECK_EQ(0, count_down_);
  60. msg_count_ = msg_count;
  61. msg_size_ = msg_size;
  62. sync_ = sync;
  63. count_down_ = msg_count_;
  64. payload_ = std::string(msg_size_, 'a');
  65. }
  66. bool OnMessageReceived(const Message& message) override {
  67. CHECK(sender_);
  68. bool handled = true;
  69. IPC_BEGIN_MESSAGE_MAP(PerformanceChannelListener, message)
  70. IPC_MESSAGE_HANDLER(TestMsg_Hello, OnHello)
  71. IPC_MESSAGE_HANDLER(TestMsg_Ping, OnPing)
  72. IPC_MESSAGE_UNHANDLED(handled = false)
  73. IPC_END_MESSAGE_MAP()
  74. return handled;
  75. }
  76. void OnHello() {
  77. // Start timing on hello.
  78. DCHECK(!perf_logger_.get());
  79. std::string test_name =
  80. base::StringPrintf("IPC_%s_Perf_%dx_%u", label_.c_str(), msg_count_,
  81. static_cast<unsigned>(msg_size_));
  82. perf_logger_ = std::make_unique<base::PerfTimeLogger>(test_name.c_str());
  83. if (sync_) {
  84. for (; count_down_ > 0; --count_down_) {
  85. std::string response;
  86. sender_->Send(new TestMsg_SyncPing(payload_, &response));
  87. DCHECK_EQ(response, payload_);
  88. }
  89. perf_logger_.reset();
  90. base::RunLoop::QuitCurrentWhenIdleDeprecated();
  91. } else {
  92. SendPong();
  93. }
  94. }
  95. void OnPing(const std::string& payload) {
  96. // Include message deserialization in latency.
  97. DCHECK_EQ(payload_.size(), payload.size());
  98. CHECK(count_down_ > 0);
  99. count_down_--;
  100. if (count_down_ == 0) {
  101. perf_logger_.reset(); // Stop the perf timer now.
  102. base::RunLoop::QuitCurrentWhenIdleDeprecated();
  103. return;
  104. }
  105. SendPong();
  106. }
  107. void SendPong() { sender_->Send(new TestMsg_Ping(payload_)); }
  108. private:
  109. std::string label_;
  110. raw_ptr<Sender> sender_;
  111. int msg_count_;
  112. size_t msg_size_;
  113. bool sync_;
  114. int count_down_;
  115. std::string payload_;
  116. std::unique_ptr<base::PerfTimeLogger> perf_logger_;
  117. };
  118. class PingPongTestParams {
  119. public:
  120. PingPongTestParams(size_t size, int count)
  121. : message_size_(size), message_count_(count) {}
  122. size_t message_size() const { return message_size_; }
  123. int message_count() const { return message_count_; }
  124. private:
  125. size_t message_size_;
  126. int message_count_;
  127. };
  128. class InterfacePassingTestParams {
  129. public:
  130. InterfacePassingTestParams(size_t rounds, size_t num_interfaces)
  131. : rounds_(rounds), num_interfaces_(num_interfaces) {}
  132. size_t rounds() const { return rounds_; }
  133. size_t num_interfaces() const { return num_interfaces_; }
  134. private:
  135. size_t rounds_;
  136. size_t num_interfaces_;
  137. };
  138. #ifdef NDEBUG
  139. const int kMultiplier = 100;
  140. #else
  141. // Debug builds on Windows run these tests orders of magnitude more slowly.
  142. const int kMultiplier = 1;
  143. #endif
  144. std::vector<PingPongTestParams> GetDefaultTestParams() {
  145. // Test several sizes. We use 12^N for message size, and limit the message
  146. // count to keep the test duration reasonable.
  147. std::vector<PingPongTestParams> list;
  148. list.push_back(PingPongTestParams(12, 500 * kMultiplier));
  149. list.push_back(PingPongTestParams(144, 500 * kMultiplier));
  150. list.push_back(PingPongTestParams(1728, 500 * kMultiplier));
  151. list.push_back(PingPongTestParams(20736, 120 * kMultiplier));
  152. list.push_back(PingPongTestParams(248832, 10 * kMultiplier));
  153. return list;
  154. }
  155. std::vector<InterfacePassingTestParams> GetDefaultInterfacePassingTestParams() {
  156. std::vector<InterfacePassingTestParams> list;
  157. list.push_back({500 * kMultiplier, 0});
  158. list.push_back({500 * kMultiplier, 1});
  159. list.push_back({500 * kMultiplier, 2});
  160. list.push_back({500 * kMultiplier, 4});
  161. list.push_back({500 * kMultiplier, 8});
  162. return list;
  163. }
  164. class MojoChannelPerfTest : public IPCChannelMojoTestBase {
  165. public:
  166. MojoChannelPerfTest() = default;
  167. ~MojoChannelPerfTest() override = default;
  168. void RunTestChannelProxyPingPong() {
  169. Init("MojoPerfTestClient");
  170. // Set up IPC channel and start client.
  171. PerformanceChannelListener listener("ChannelProxy");
  172. auto channel_proxy = IPC::ChannelProxy::Create(
  173. TakeHandle().release(), IPC::Channel::MODE_SERVER, &listener,
  174. GetIOThreadTaskRunner(), base::ThreadTaskRunnerHandle::Get());
  175. listener.Init(channel_proxy.get());
  176. LockThreadAffinity thread_locker(kSharedCore);
  177. std::vector<PingPongTestParams> params = GetDefaultTestParams();
  178. for (size_t i = 0; i < params.size(); i++) {
  179. listener.SetTestParams(params[i].message_count(),
  180. params[i].message_size(), false);
  181. // This initial message will kick-start the ping-pong of messages.
  182. channel_proxy->Send(new TestMsg_Hello);
  183. // Run message loop.
  184. base::RunLoop().Run();
  185. }
  186. // Send quit message.
  187. channel_proxy->Send(new TestMsg_Quit);
  188. EXPECT_TRUE(WaitForClientShutdown());
  189. channel_proxy.reset();
  190. }
  191. void RunTestChannelProxySyncPing() {
  192. Init("MojoPerfTestClient");
  193. // Set up IPC channel and start client.
  194. PerformanceChannelListener listener("ChannelProxy");
  195. base::WaitableEvent shutdown_event(
  196. base::WaitableEvent::ResetPolicy::MANUAL,
  197. base::WaitableEvent::InitialState::NOT_SIGNALED);
  198. auto channel_proxy = IPC::SyncChannel::Create(
  199. TakeHandle().release(), IPC::Channel::MODE_SERVER, &listener,
  200. GetIOThreadTaskRunner(), base::ThreadTaskRunnerHandle::Get(), false,
  201. &shutdown_event);
  202. listener.Init(channel_proxy.get());
  203. LockThreadAffinity thread_locker(kSharedCore);
  204. std::vector<PingPongTestParams> params = GetDefaultTestParams();
  205. for (size_t i = 0; i < params.size(); i++) {
  206. listener.SetTestParams(params[i].message_count(),
  207. params[i].message_size(), true);
  208. // This initial message will kick-start the ping-pong of messages.
  209. channel_proxy->Send(new TestMsg_Hello);
  210. // Run message loop.
  211. base::RunLoop().Run();
  212. }
  213. // Send quit message.
  214. channel_proxy->Send(new TestMsg_Quit);
  215. EXPECT_TRUE(WaitForClientShutdown());
  216. channel_proxy.reset();
  217. }
  218. };
  219. TEST_F(MojoChannelPerfTest, ChannelProxyPingPong) {
  220. RunTestChannelProxyPingPong();
  221. base::RunLoop run_loop;
  222. run_loop.RunUntilIdle();
  223. }
  224. TEST_F(MojoChannelPerfTest, ChannelProxySyncPing) {
  225. RunTestChannelProxySyncPing();
  226. base::RunLoop run_loop;
  227. run_loop.RunUntilIdle();
  228. }
  229. MULTIPROCESS_TEST_MAIN(MojoPerfTestClientTestChildMain) {
  230. MojoPerfTestClient client;
  231. int rv = mojo::core::test::MultiprocessTestHelper::RunClientMain(
  232. base::BindOnce(&MojoPerfTestClient::Run, base::Unretained(&client)),
  233. true /* pass_pipe_ownership_to_main */);
  234. base::RunLoop run_loop;
  235. run_loop.RunUntilIdle();
  236. return rv;
  237. }
  238. class MojoInterfacePerfTest : public mojo::core::test::MojoTestBase {
  239. public:
  240. MojoInterfacePerfTest() : message_count_(0), count_down_(0) {}
  241. MojoInterfacePerfTest(const MojoInterfacePerfTest&) = delete;
  242. MojoInterfacePerfTest& operator=(const MojoInterfacePerfTest&) = delete;
  243. protected:
  244. void RunPingPongServer(MojoHandle mp, const std::string& label) {
  245. label_ = label;
  246. mojo::MessagePipeHandle mp_handle(mp);
  247. mojo::ScopedMessagePipeHandle scoped_mp(mp_handle);
  248. ping_receiver_.Bind(
  249. mojo::PendingRemote<IPC::mojom::Reflector>(std::move(scoped_mp), 0u));
  250. LockThreadAffinity thread_locker(kSharedCore);
  251. std::vector<PingPongTestParams> params = GetDefaultTestParams();
  252. for (size_t i = 0; i < params.size(); i++) {
  253. ping_receiver_->Ping("hello",
  254. base::BindOnce(&MojoInterfacePerfTest::OnPong,
  255. base::Unretained(this)));
  256. message_count_ = count_down_ = params[i].message_count();
  257. payload_ = std::string(params[i].message_size(), 'a');
  258. base::RunLoop().Run();
  259. }
  260. ping_receiver_->Quit();
  261. std::ignore = ping_receiver_.Unbind().PassPipe().release();
  262. }
  263. void OnPong(const std::string& value) {
  264. if (value == "hello") {
  265. DCHECK(!perf_logger_.get());
  266. std::string test_name =
  267. base::StringPrintf("IPC_%s_Perf_%dx_%zu", label_.c_str(),
  268. message_count_, payload_.size());
  269. perf_logger_ = std::make_unique<base::PerfTimeLogger>(test_name.c_str());
  270. } else {
  271. DCHECK_EQ(payload_.size(), value.size());
  272. CHECK(count_down_ > 0);
  273. count_down_--;
  274. if (count_down_ == 0) {
  275. perf_logger_.reset();
  276. base::RunLoop::QuitCurrentWhenIdleDeprecated();
  277. return;
  278. }
  279. }
  280. if (sync_) {
  281. for (int i = 0; i < count_down_; ++i) {
  282. std::string response;
  283. ping_receiver_->SyncPing(payload_, &response);
  284. DCHECK_EQ(response, payload_);
  285. }
  286. perf_logger_.reset();
  287. base::RunLoop::QuitCurrentWhenIdleDeprecated();
  288. } else {
  289. ping_receiver_->Ping(payload_,
  290. base::BindOnce(&MojoInterfacePerfTest::OnPong,
  291. base::Unretained(this)));
  292. }
  293. }
  294. static int RunPingPongClient(MojoHandle mp) {
  295. mojo::MessagePipeHandle mp_handle(mp);
  296. mojo::ScopedMessagePipeHandle scoped_mp(mp_handle);
  297. LockThreadAffinity thread_locker(kSharedCore);
  298. // In single process mode, this is running in a task and by default other
  299. // tasks (in particular, the binding) won't run. To keep the single process
  300. // and multi-process code paths the same, enable nestable tasks.
  301. base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed);
  302. ReflectorImpl impl(std::move(scoped_mp), run_loop.QuitWhenIdleClosure());
  303. run_loop.Run();
  304. return 0;
  305. }
  306. bool sync_ = false;
  307. private:
  308. int message_count_;
  309. int count_down_;
  310. std::string label_;
  311. std::string payload_;
  312. mojo::Remote<IPC::mojom::Reflector> ping_receiver_;
  313. std::unique_ptr<base::PerfTimeLogger> perf_logger_;
  314. };
  315. class InterfacePassingTestDriverImpl : public mojom::InterfacePassingTestDriver,
  316. public mojom::PingReceiver {
  317. public:
  318. InterfacePassingTestDriverImpl(mojo::ScopedMessagePipeHandle handle,
  319. base::OnceClosure quit_closure)
  320. : receiver_(this,
  321. mojo::PendingReceiver<mojom::InterfacePassingTestDriver>(
  322. std::move(handle))),
  323. quit_closure_(std::move(quit_closure)) {}
  324. ~InterfacePassingTestDriverImpl() override {
  325. std::ignore = receiver_.Unbind().PassPipe().release();
  326. }
  327. private:
  328. // mojom::InterfacePassingTestDriver implementation:
  329. void Init(InitCallback callback) override { std::move(callback).Run(); }
  330. void GetPingReceiver(
  331. std::vector<mojo::PendingReceiver<mojom::PingReceiver>> receivers,
  332. GetPingReceiverCallback callback) override {
  333. for (auto& receiver : receivers)
  334. ping_receiver_receivers_.Add(this, std::move(receiver));
  335. ping_receiver_receivers_.Clear();
  336. std::move(callback).Run();
  337. }
  338. void GetAssociatedPingReceiver(
  339. std::vector<mojo::PendingAssociatedReceiver<mojom::PingReceiver>>
  340. receivers,
  341. GetAssociatedPingReceiverCallback callback) override {
  342. for (auto& receiver : receivers)
  343. ping_receiver_associated_receivers_.Add(this, std::move(receiver));
  344. ping_receiver_associated_receivers_.Clear();
  345. std::move(callback).Run();
  346. }
  347. void Quit() override {
  348. if (quit_closure_)
  349. std::move(quit_closure_).Run();
  350. }
  351. // mojom::PingReceiver implementation:
  352. void Ping(PingCallback callback) override { std::move(callback).Run(); }
  353. mojo::ReceiverSet<mojom::PingReceiver> ping_receiver_receivers_;
  354. mojo::AssociatedReceiverSet<mojom::PingReceiver>
  355. ping_receiver_associated_receivers_;
  356. mojo::Receiver<mojom::InterfacePassingTestDriver> receiver_;
  357. base::OnceClosure quit_closure_;
  358. };
  359. class MojoInterfacePassingPerfTest : public mojo::core::test::MojoTestBase {
  360. public:
  361. MojoInterfacePassingPerfTest() = default;
  362. MojoInterfacePassingPerfTest(const MojoInterfacePassingPerfTest&) = delete;
  363. MojoInterfacePassingPerfTest& operator=(const MojoInterfacePassingPerfTest&) =
  364. delete;
  365. protected:
  366. void RunInterfacePassingServer(MojoHandle mp,
  367. const std::string& label,
  368. bool associated) {
  369. label_ = label;
  370. associated_ = associated;
  371. mojo::MessagePipeHandle mp_handle(mp);
  372. mojo::ScopedMessagePipeHandle scoped_mp(mp_handle);
  373. driver_remote_.Bind(mojo::PendingRemote<mojom::InterfacePassingTestDriver>(
  374. std::move(scoped_mp), 0u));
  375. auto params = GetDefaultInterfacePassingTestParams();
  376. LockThreadAffinity thread_locker(kSharedCore);
  377. for (size_t i = 0; i < params.size(); ++i) {
  378. driver_remote_->Init(
  379. base::BindOnce(&MojoInterfacePassingPerfTest::OnInitCallback,
  380. base::Unretained(this)));
  381. rounds_ = count_down_ = params[i].rounds();
  382. num_interfaces_ = params[i].num_interfaces();
  383. base::RunLoop run_loop;
  384. quit_closure_ = run_loop.QuitWhenIdleClosure();
  385. run_loop.Run();
  386. }
  387. driver_remote_->Quit();
  388. std::ignore = driver_remote_.Unbind().PassPipe().release();
  389. }
  390. void OnInitCallback() {
  391. DCHECK(!perf_logger_.get());
  392. std::string test_name = base::StringPrintf(
  393. "IPC_%s_Perf_%zux_%zu", label_.c_str(), rounds_, num_interfaces_);
  394. perf_logger_ = std::make_unique<base::PerfTimeLogger>(test_name.c_str());
  395. DoNextRound();
  396. }
  397. void DoNextRound() {
  398. if (associated_) {
  399. std::vector<mojo::AssociatedRemote<mojom::PingReceiver>>
  400. associated_remotes(num_interfaces_);
  401. std::vector<mojo::PendingAssociatedReceiver<mojom::PingReceiver>>
  402. receivers(num_interfaces_);
  403. for (size_t i = 0; i < num_interfaces_; ++i) {
  404. receivers[i] = associated_remotes[i].BindNewEndpointAndPassReceiver();
  405. // Force the interface pointer to do full initialization.
  406. associated_remotes[i].get();
  407. }
  408. driver_remote_->GetAssociatedPingReceiver(
  409. std::move(receivers),
  410. base::BindOnce(&MojoInterfacePassingPerfTest::OnGetReceiverCallback,
  411. base::Unretained(this)));
  412. } else {
  413. std::vector<mojo::Remote<mojom::PingReceiver>> remotes(num_interfaces_);
  414. std::vector<mojo::PendingReceiver<mojom::PingReceiver>> receivers(
  415. num_interfaces_);
  416. for (size_t i = 0; i < num_interfaces_; ++i) {
  417. receivers[i] = remotes[i].BindNewPipeAndPassReceiver();
  418. // Force the interface pointer to do full initialization.
  419. remotes[i].get();
  420. }
  421. driver_remote_->GetPingReceiver(
  422. std::move(receivers),
  423. base::BindOnce(&MojoInterfacePassingPerfTest::OnGetReceiverCallback,
  424. base::Unretained(this)));
  425. }
  426. }
  427. void OnGetReceiverCallback() {
  428. CHECK_GT(count_down_, 0u);
  429. count_down_--;
  430. if (count_down_ == 0) {
  431. perf_logger_.reset();
  432. std::move(quit_closure_).Run();
  433. return;
  434. }
  435. DoNextRound();
  436. }
  437. static int RunInterfacePassingClient(MojoHandle mp) {
  438. mojo::MessagePipeHandle mp_handle(mp);
  439. mojo::ScopedMessagePipeHandle scoped_mp(mp_handle);
  440. LockThreadAffinity thread_locker(kSharedCore);
  441. // In single process mode, this is running in a task and by default other
  442. // tasks (in particular, the binding) won't run. To keep the single process
  443. // and multi-process code paths the same, enable nestable tasks.
  444. base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed);
  445. InterfacePassingTestDriverImpl impl(std::move(scoped_mp),
  446. run_loop.QuitWhenIdleClosure());
  447. run_loop.Run();
  448. return 0;
  449. }
  450. private:
  451. size_t rounds_ = 0;
  452. size_t count_down_ = 0;
  453. size_t num_interfaces_ = 0;
  454. std::string label_;
  455. bool associated_ = false;
  456. std::unique_ptr<base::PerfTimeLogger> perf_logger_;
  457. mojo::Remote<mojom::InterfacePassingTestDriver> driver_remote_;
  458. base::OnceClosure quit_closure_;
  459. };
  460. DEFINE_TEST_CLIENT_WITH_PIPE(InterfacePassingClient,
  461. MojoInterfacePassingPerfTest,
  462. h) {
  463. base::test::SingleThreadTaskEnvironment task_environment;
  464. return RunInterfacePassingClient(h);
  465. }
  466. enum class InProcessMessageMode {
  467. kSerialized,
  468. kUnserialized,
  469. };
  470. template <class TestBase>
  471. class InProcessPerfTest
  472. : public TestBase,
  473. public testing::WithParamInterface<InProcessMessageMode> {
  474. public:
  475. InProcessPerfTest() {
  476. switch (GetParam()) {
  477. case InProcessMessageMode::kSerialized:
  478. mojo::Connector::OverrideDefaultSerializationBehaviorForTesting(
  479. mojo::Connector::OutgoingSerializationMode::kEager,
  480. mojo::Connector::IncomingSerializationMode::kDispatchAsIs);
  481. break;
  482. case InProcessMessageMode::kUnserialized:
  483. mojo::Connector::OverrideDefaultSerializationBehaviorForTesting(
  484. mojo::Connector::OutgoingSerializationMode::kLazy,
  485. mojo::Connector::IncomingSerializationMode::kDispatchAsIs);
  486. break;
  487. }
  488. }
  489. };
  490. using MojoInProcessInterfacePerfTest = InProcessPerfTest<MojoInterfacePerfTest>;
  491. using MojoInProcessInterfacePassingPerfTest =
  492. InProcessPerfTest<MojoInterfacePassingPerfTest>;
  493. DEFINE_TEST_CLIENT_WITH_PIPE(PingPongClient, MojoInterfacePerfTest, h) {
  494. base::test::SingleThreadTaskEnvironment task_environment;
  495. return RunPingPongClient(h);
  496. }
  497. // Similar to MojoChannelPerfTest above, but uses a Mojo interface instead of
  498. // raw IPC::Messages.
  499. TEST_F(MojoInterfacePerfTest, MultiprocessPingPong) {
  500. RunTestClient("PingPongClient", [&](MojoHandle h) {
  501. base::test::SingleThreadTaskEnvironment task_environment;
  502. RunPingPongServer(h, "Multiprocess");
  503. });
  504. }
  505. TEST_F(MojoInterfacePerfTest, MultiprocessSyncPing) {
  506. sync_ = true;
  507. RunTestClient("PingPongClient", [&](MojoHandle h) {
  508. base::test::SingleThreadTaskEnvironment task_environment;
  509. RunPingPongServer(h, "MultiprocessSync");
  510. });
  511. }
  512. TEST_F(MojoInterfacePassingPerfTest, MultiprocessInterfacePassing) {
  513. RunTestClient("InterfacePassingClient", [&](MojoHandle h) {
  514. base::test::SingleThreadTaskEnvironment task_environment;
  515. RunInterfacePassingServer(h, "InterfacePassing", false /* associated */);
  516. });
  517. }
  518. TEST_F(MojoInterfacePassingPerfTest, MultiprocessAssociatedInterfacePassing) {
  519. RunTestClient("InterfacePassingClient", [&](MojoHandle h) {
  520. base::test::SingleThreadTaskEnvironment task_environment;
  521. RunInterfacePassingServer(h, "AssociatedInterfacePassing",
  522. true /* associated*/);
  523. });
  524. }
  525. // A single process version of the above test.
  526. TEST_P(MojoInProcessInterfacePerfTest, MultiThreadPingPong) {
  527. MojoHandle server_handle, client_handle;
  528. CreateMessagePipe(&server_handle, &client_handle);
  529. base::Thread client_thread("PingPongClient");
  530. client_thread.Start();
  531. client_thread.task_runner()->PostTask(
  532. FROM_HERE,
  533. base::BindOnce(base::IgnoreResult(&RunPingPongClient), client_handle));
  534. base::test::SingleThreadTaskEnvironment task_environment;
  535. RunPingPongServer(server_handle, "SingleProcess");
  536. }
  537. TEST_P(MojoInProcessInterfacePerfTest, SingleThreadPingPong) {
  538. MojoHandle server_handle, client_handle;
  539. CreateMessagePipe(&server_handle, &client_handle);
  540. base::test::SingleThreadTaskEnvironment task_environment;
  541. mojo::MessagePipeHandle mp_handle(client_handle);
  542. mojo::ScopedMessagePipeHandle scoped_mp(mp_handle);
  543. LockThreadAffinity thread_locker(kSharedCore);
  544. ReflectorImpl impl(std::move(scoped_mp), base::OnceClosure());
  545. RunPingPongServer(server_handle, "SingleProcess");
  546. }
  547. INSTANTIATE_TEST_SUITE_P(All,
  548. MojoInProcessInterfacePerfTest,
  549. testing::Values(InProcessMessageMode::kSerialized,
  550. InProcessMessageMode::kUnserialized));
  551. TEST_P(MojoInProcessInterfacePassingPerfTest, MultiThreadInterfacePassing) {
  552. MojoHandle server_handle, client_handle;
  553. CreateMessagePipe(&server_handle, &client_handle);
  554. base::Thread client_thread("InterfacePassingClient");
  555. client_thread.Start();
  556. client_thread.task_runner()->PostTask(
  557. FROM_HERE, base::BindOnce(base::IgnoreResult(&RunInterfacePassingClient),
  558. client_handle));
  559. base::test::SingleThreadTaskEnvironment task_environment;
  560. RunInterfacePassingServer(server_handle, "SingleProcess",
  561. false /* associated */);
  562. }
  563. TEST_P(MojoInProcessInterfacePassingPerfTest,
  564. MultiThreadAssociatedInterfacePassing) {
  565. MojoHandle server_handle, client_handle;
  566. CreateMessagePipe(&server_handle, &client_handle);
  567. base::Thread client_thread("InterfacePassingClient");
  568. client_thread.Start();
  569. client_thread.task_runner()->PostTask(
  570. FROM_HERE, base::BindOnce(base::IgnoreResult(&RunInterfacePassingClient),
  571. client_handle));
  572. base::test::SingleThreadTaskEnvironment task_environment;
  573. RunInterfacePassingServer(server_handle, "SingleProcess",
  574. true /* associated */);
  575. }
  576. TEST_P(MojoInProcessInterfacePassingPerfTest, SingleThreadInterfacePassing) {
  577. MojoHandle server_handle, client_handle;
  578. CreateMessagePipe(&server_handle, &client_handle);
  579. base::test::SingleThreadTaskEnvironment task_environment;
  580. mojo::MessagePipeHandle mp_handle(client_handle);
  581. mojo::ScopedMessagePipeHandle scoped_mp(mp_handle);
  582. LockThreadAffinity thread_locker(kSharedCore);
  583. InterfacePassingTestDriverImpl impl(std::move(scoped_mp),
  584. base::OnceClosure());
  585. RunInterfacePassingServer(server_handle, "SingleProcess",
  586. false /* associated */);
  587. }
  588. TEST_P(MojoInProcessInterfacePassingPerfTest,
  589. SingleThreadAssociatedInterfacePassing) {
  590. MojoHandle server_handle, client_handle;
  591. CreateMessagePipe(&server_handle, &client_handle);
  592. base::test::SingleThreadTaskEnvironment task_environment;
  593. mojo::MessagePipeHandle mp_handle(client_handle);
  594. mojo::ScopedMessagePipeHandle scoped_mp(mp_handle);
  595. LockThreadAffinity thread_locker(kSharedCore);
  596. InterfacePassingTestDriverImpl impl(std::move(scoped_mp),
  597. base::OnceClosure());
  598. RunInterfacePassingServer(server_handle, "SingleProcess",
  599. true /* associated */);
  600. }
  601. INSTANTIATE_TEST_SUITE_P(All,
  602. MojoInProcessInterfacePassingPerfTest,
  603. testing::Values(InProcessMessageMode::kSerialized,
  604. InProcessMessageMode::kUnserialized));
  605. class CallbackPerfTest : public testing::Test {
  606. public:
  607. CallbackPerfTest()
  608. : client_thread_("PingPongClient"), message_count_(0), count_down_(0) {}
  609. CallbackPerfTest(const CallbackPerfTest&) = delete;
  610. CallbackPerfTest& operator=(const CallbackPerfTest&) = delete;
  611. protected:
  612. void RunMultiThreadPingPongServer() {
  613. client_thread_.Start();
  614. LockThreadAffinity thread_locker(kSharedCore);
  615. std::vector<PingPongTestParams> params = GetDefaultTestParams();
  616. for (size_t i = 0; i < params.size(); i++) {
  617. std::string hello("hello");
  618. client_thread_.task_runner()->PostTask(
  619. FROM_HERE, base::BindOnce(&CallbackPerfTest::Ping,
  620. base::Unretained(this), hello));
  621. message_count_ = count_down_ = params[i].message_count();
  622. payload_ = std::string(params[i].message_size(), 'a');
  623. base::RunLoop().Run();
  624. }
  625. }
  626. void Ping(const std::string& value) {
  627. task_environment_.GetMainThreadTaskRunner()->PostTask(
  628. FROM_HERE, base::BindOnce(&CallbackPerfTest::OnPong,
  629. base::Unretained(this), value));
  630. }
  631. void OnPong(const std::string& value) {
  632. if (value == "hello") {
  633. DCHECK(!perf_logger_.get());
  634. std::string test_name =
  635. base::StringPrintf("Callback_MultiProcess_Perf_%dx_%zu",
  636. message_count_, payload_.size());
  637. perf_logger_ = std::make_unique<base::PerfTimeLogger>(test_name.c_str());
  638. } else {
  639. DCHECK_EQ(payload_.size(), value.size());
  640. CHECK(count_down_ > 0);
  641. count_down_--;
  642. if (count_down_ == 0) {
  643. perf_logger_.reset();
  644. base::RunLoop::QuitCurrentWhenIdleDeprecated();
  645. return;
  646. }
  647. }
  648. client_thread_.task_runner()->PostTask(
  649. FROM_HERE, base::BindOnce(&CallbackPerfTest::Ping,
  650. base::Unretained(this), payload_));
  651. }
  652. void RunSingleThreadNoPostTaskPingPongServer() {
  653. LockThreadAffinity thread_locker(kSharedCore);
  654. std::vector<PingPongTestParams> params = GetDefaultTestParams();
  655. base::RepeatingCallback<void(
  656. const std::string&, int,
  657. base::OnceCallback<void(const std::string&, int)>)>
  658. ping =
  659. base::BindRepeating(&CallbackPerfTest::SingleThreadPingNoPostTask,
  660. base::Unretained(this));
  661. for (size_t i = 0; i < params.size(); i++) {
  662. payload_ = std::string(params[i].message_size(), 'a');
  663. std::string test_name =
  664. base::StringPrintf("Callback_SingleThreadNoPostTask_Perf_%dx_%zu",
  665. params[i].message_count(), payload_.size());
  666. perf_logger_ = std::make_unique<base::PerfTimeLogger>(test_name.c_str());
  667. for (int j = 0; j < params[i].message_count(); ++j) {
  668. ping.Run(payload_, j,
  669. base::BindOnce(&CallbackPerfTest::SingleThreadPongNoPostTask,
  670. base::Unretained(this)));
  671. }
  672. perf_logger_.reset();
  673. }
  674. }
  675. void SingleThreadPingNoPostTask(
  676. const std::string& value,
  677. int i,
  678. base::OnceCallback<void(const std::string&, int)> pong) {
  679. std::move(pong).Run(value, i);
  680. }
  681. void SingleThreadPongNoPostTask(const std::string& value, int i) {}
  682. void RunSingleThreadPostTaskPingPongServer() {
  683. LockThreadAffinity thread_locker(kSharedCore);
  684. std::vector<PingPongTestParams> params = GetDefaultTestParams();
  685. for (size_t i = 0; i < params.size(); i++) {
  686. std::string hello("hello");
  687. base::ThreadTaskRunnerHandle::Get()->PostTask(
  688. FROM_HERE, base::BindOnce(&CallbackPerfTest::SingleThreadPingPostTask,
  689. base::Unretained(this), hello));
  690. message_count_ = count_down_ = params[i].message_count();
  691. payload_ = std::string(params[i].message_size(), 'a');
  692. base::RunLoop().Run();
  693. }
  694. }
  695. void SingleThreadPingPostTask(const std::string& value) {
  696. base::ThreadTaskRunnerHandle::Get()->PostTask(
  697. FROM_HERE, base::BindOnce(&CallbackPerfTest::SingleThreadPongPostTask,
  698. base::Unretained(this), value));
  699. }
  700. void SingleThreadPongPostTask(const std::string& value) {
  701. if (value == "hello") {
  702. DCHECK(!perf_logger_.get());
  703. std::string test_name =
  704. base::StringPrintf("Callback_SingleThreadPostTask_Perf_%dx_%zu",
  705. message_count_, payload_.size());
  706. perf_logger_ = std::make_unique<base::PerfTimeLogger>(test_name.c_str());
  707. } else {
  708. DCHECK_EQ(payload_.size(), value.size());
  709. CHECK(count_down_ > 0);
  710. count_down_--;
  711. if (count_down_ == 0) {
  712. perf_logger_.reset();
  713. base::RunLoop::QuitCurrentWhenIdleDeprecated();
  714. return;
  715. }
  716. }
  717. base::ThreadTaskRunnerHandle::Get()->PostTask(
  718. FROM_HERE, base::BindOnce(&CallbackPerfTest::SingleThreadPingPostTask,
  719. base::Unretained(this), payload_));
  720. }
  721. private:
  722. base::Thread client_thread_;
  723. base::test::SingleThreadTaskEnvironment task_environment_;
  724. int message_count_;
  725. int count_down_;
  726. std::string payload_;
  727. std::unique_ptr<base::PerfTimeLogger> perf_logger_;
  728. };
  729. // Sends the same data as above using PostTask to a different thread instead of
  730. // IPCs for comparison.
  731. TEST_F(CallbackPerfTest, MultiThreadPingPong) {
  732. RunMultiThreadPingPongServer();
  733. }
  734. // Sends the same data as above using PostTask to the same thread.
  735. TEST_F(CallbackPerfTest, SingleThreadPostTaskPingPong) {
  736. RunSingleThreadPostTaskPingPongServer();
  737. }
  738. // Sends the same data as above without using PostTask to the same thread.
  739. TEST_F(CallbackPerfTest, SingleThreadNoPostTaskPingPong) {
  740. RunSingleThreadNoPostTaskPingPongServer();
  741. }
  742. } // namespace
  743. } // namespace IPC