123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890 |
- // Copyright 2014 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include <stddef.h>
- #include <memory>
- #include <tuple>
- #include "base/bind.h"
- #include "base/callback.h"
- #include "base/memory/ptr_util.h"
- #include "base/memory/raw_ptr.h"
- #include "base/process/process_metrics.h"
- #include "base/run_loop.h"
- #include "base/strings/stringprintf.h"
- #include "base/synchronization/waitable_event.h"
- #include "base/test/perf_time_logger.h"
- #include "base/test/task_environment.h"
- #include "base/threading/thread.h"
- #include "base/threading/thread_task_runner_handle.h"
- #include "base/time/time.h"
- #include "build/build_config.h"
- #include "ipc/ipc_channel_mojo.h"
- #include "ipc/ipc_perftest_messages.h"
- #include "ipc/ipc_perftest_util.h"
- #include "ipc/ipc_sync_channel.h"
- #include "ipc/ipc_test.mojom.h"
- #include "ipc/ipc_test_base.h"
- #include "mojo/core/embedder/embedder.h"
- #include "mojo/core/test/mojo_test_base.h"
- #include "mojo/core/test/multiprocess_test_helper.h"
- #include "mojo/public/cpp/bindings/associated_receiver_set.h"
- #include "mojo/public/cpp/bindings/associated_remote.h"
- #include "mojo/public/cpp/bindings/pending_associated_receiver.h"
- #include "mojo/public/cpp/bindings/pending_receiver.h"
- #include "mojo/public/cpp/bindings/pending_remote.h"
- #include "mojo/public/cpp/bindings/receiver.h"
- #include "mojo/public/cpp/bindings/receiver_set.h"
- #include "mojo/public/cpp/bindings/remote.h"
- #include "mojo/public/cpp/system/message_pipe.h"
- namespace IPC {
- namespace {
- class PerformanceChannelListener : public Listener {
- public:
- explicit PerformanceChannelListener(const std::string& label)
- : label_(label),
- sender_(nullptr),
- msg_count_(0),
- msg_size_(0),
- sync_(false),
- count_down_(0) {
- VLOG(1) << "Server listener up";
- }
- ~PerformanceChannelListener() override { VLOG(1) << "Server listener down"; }
- void Init(Sender* sender) {
- DCHECK(!sender_);
- sender_ = sender;
- }
- // Call this before running the message loop.
- void SetTestParams(int msg_count, size_t msg_size, bool sync) {
- DCHECK_EQ(0, count_down_);
- msg_count_ = msg_count;
- msg_size_ = msg_size;
- sync_ = sync;
- count_down_ = msg_count_;
- payload_ = std::string(msg_size_, 'a');
- }
- bool OnMessageReceived(const Message& message) override {
- CHECK(sender_);
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(PerformanceChannelListener, message)
- IPC_MESSAGE_HANDLER(TestMsg_Hello, OnHello)
- IPC_MESSAGE_HANDLER(TestMsg_Ping, OnPing)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
- }
- void OnHello() {
- // Start timing on hello.
- DCHECK(!perf_logger_.get());
- std::string test_name =
- base::StringPrintf("IPC_%s_Perf_%dx_%u", label_.c_str(), msg_count_,
- static_cast<unsigned>(msg_size_));
- perf_logger_ = std::make_unique<base::PerfTimeLogger>(test_name.c_str());
- if (sync_) {
- for (; count_down_ > 0; --count_down_) {
- std::string response;
- sender_->Send(new TestMsg_SyncPing(payload_, &response));
- DCHECK_EQ(response, payload_);
- }
- perf_logger_.reset();
- base::RunLoop::QuitCurrentWhenIdleDeprecated();
- } else {
- SendPong();
- }
- }
- void OnPing(const std::string& payload) {
- // Include message deserialization in latency.
- DCHECK_EQ(payload_.size(), payload.size());
- CHECK(count_down_ > 0);
- count_down_--;
- if (count_down_ == 0) {
- perf_logger_.reset(); // Stop the perf timer now.
- base::RunLoop::QuitCurrentWhenIdleDeprecated();
- return;
- }
- SendPong();
- }
- void SendPong() { sender_->Send(new TestMsg_Ping(payload_)); }
- private:
- std::string label_;
- raw_ptr<Sender> sender_;
- int msg_count_;
- size_t msg_size_;
- bool sync_;
- int count_down_;
- std::string payload_;
- std::unique_ptr<base::PerfTimeLogger> perf_logger_;
- };
- class PingPongTestParams {
- public:
- PingPongTestParams(size_t size, int count)
- : message_size_(size), message_count_(count) {}
- size_t message_size() const { return message_size_; }
- int message_count() const { return message_count_; }
- private:
- size_t message_size_;
- int message_count_;
- };
- class InterfacePassingTestParams {
- public:
- InterfacePassingTestParams(size_t rounds, size_t num_interfaces)
- : rounds_(rounds), num_interfaces_(num_interfaces) {}
- size_t rounds() const { return rounds_; }
- size_t num_interfaces() const { return num_interfaces_; }
- private:
- size_t rounds_;
- size_t num_interfaces_;
- };
- #ifdef NDEBUG
- const int kMultiplier = 100;
- #else
- // Debug builds on Windows run these tests orders of magnitude more slowly.
- const int kMultiplier = 1;
- #endif
- std::vector<PingPongTestParams> GetDefaultTestParams() {
- // Test several sizes. We use 12^N for message size, and limit the message
- // count to keep the test duration reasonable.
- std::vector<PingPongTestParams> list;
- list.push_back(PingPongTestParams(12, 500 * kMultiplier));
- list.push_back(PingPongTestParams(144, 500 * kMultiplier));
- list.push_back(PingPongTestParams(1728, 500 * kMultiplier));
- list.push_back(PingPongTestParams(20736, 120 * kMultiplier));
- list.push_back(PingPongTestParams(248832, 10 * kMultiplier));
- return list;
- }
- std::vector<InterfacePassingTestParams> GetDefaultInterfacePassingTestParams() {
- std::vector<InterfacePassingTestParams> list;
- list.push_back({500 * kMultiplier, 0});
- list.push_back({500 * kMultiplier, 1});
- list.push_back({500 * kMultiplier, 2});
- list.push_back({500 * kMultiplier, 4});
- list.push_back({500 * kMultiplier, 8});
- return list;
- }
- class MojoChannelPerfTest : public IPCChannelMojoTestBase {
- public:
- MojoChannelPerfTest() = default;
- ~MojoChannelPerfTest() override = default;
- void RunTestChannelProxyPingPong() {
- Init("MojoPerfTestClient");
- // Set up IPC channel and start client.
- PerformanceChannelListener listener("ChannelProxy");
- auto channel_proxy = IPC::ChannelProxy::Create(
- TakeHandle().release(), IPC::Channel::MODE_SERVER, &listener,
- GetIOThreadTaskRunner(), base::ThreadTaskRunnerHandle::Get());
- listener.Init(channel_proxy.get());
- LockThreadAffinity thread_locker(kSharedCore);
- std::vector<PingPongTestParams> params = GetDefaultTestParams();
- for (size_t i = 0; i < params.size(); i++) {
- listener.SetTestParams(params[i].message_count(),
- params[i].message_size(), false);
- // This initial message will kick-start the ping-pong of messages.
- channel_proxy->Send(new TestMsg_Hello);
- // Run message loop.
- base::RunLoop().Run();
- }
- // Send quit message.
- channel_proxy->Send(new TestMsg_Quit);
- EXPECT_TRUE(WaitForClientShutdown());
- channel_proxy.reset();
- }
- void RunTestChannelProxySyncPing() {
- Init("MojoPerfTestClient");
- // Set up IPC channel and start client.
- PerformanceChannelListener listener("ChannelProxy");
- base::WaitableEvent shutdown_event(
- base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
- auto channel_proxy = IPC::SyncChannel::Create(
- TakeHandle().release(), IPC::Channel::MODE_SERVER, &listener,
- GetIOThreadTaskRunner(), base::ThreadTaskRunnerHandle::Get(), false,
- &shutdown_event);
- listener.Init(channel_proxy.get());
- LockThreadAffinity thread_locker(kSharedCore);
- std::vector<PingPongTestParams> params = GetDefaultTestParams();
- for (size_t i = 0; i < params.size(); i++) {
- listener.SetTestParams(params[i].message_count(),
- params[i].message_size(), true);
- // This initial message will kick-start the ping-pong of messages.
- channel_proxy->Send(new TestMsg_Hello);
- // Run message loop.
- base::RunLoop().Run();
- }
- // Send quit message.
- channel_proxy->Send(new TestMsg_Quit);
- EXPECT_TRUE(WaitForClientShutdown());
- channel_proxy.reset();
- }
- };
- TEST_F(MojoChannelPerfTest, ChannelProxyPingPong) {
- RunTestChannelProxyPingPong();
- base::RunLoop run_loop;
- run_loop.RunUntilIdle();
- }
- TEST_F(MojoChannelPerfTest, ChannelProxySyncPing) {
- RunTestChannelProxySyncPing();
- base::RunLoop run_loop;
- run_loop.RunUntilIdle();
- }
- MULTIPROCESS_TEST_MAIN(MojoPerfTestClientTestChildMain) {
- MojoPerfTestClient client;
- int rv = mojo::core::test::MultiprocessTestHelper::RunClientMain(
- base::BindOnce(&MojoPerfTestClient::Run, base::Unretained(&client)),
- true /* pass_pipe_ownership_to_main */);
- base::RunLoop run_loop;
- run_loop.RunUntilIdle();
- return rv;
- }
- class MojoInterfacePerfTest : public mojo::core::test::MojoTestBase {
- public:
- MojoInterfacePerfTest() : message_count_(0), count_down_(0) {}
- MojoInterfacePerfTest(const MojoInterfacePerfTest&) = delete;
- MojoInterfacePerfTest& operator=(const MojoInterfacePerfTest&) = delete;
- protected:
- void RunPingPongServer(MojoHandle mp, const std::string& label) {
- label_ = label;
- mojo::MessagePipeHandle mp_handle(mp);
- mojo::ScopedMessagePipeHandle scoped_mp(mp_handle);
- ping_receiver_.Bind(
- mojo::PendingRemote<IPC::mojom::Reflector>(std::move(scoped_mp), 0u));
- LockThreadAffinity thread_locker(kSharedCore);
- std::vector<PingPongTestParams> params = GetDefaultTestParams();
- for (size_t i = 0; i < params.size(); i++) {
- ping_receiver_->Ping("hello",
- base::BindOnce(&MojoInterfacePerfTest::OnPong,
- base::Unretained(this)));
- message_count_ = count_down_ = params[i].message_count();
- payload_ = std::string(params[i].message_size(), 'a');
- base::RunLoop().Run();
- }
- ping_receiver_->Quit();
- std::ignore = ping_receiver_.Unbind().PassPipe().release();
- }
- void OnPong(const std::string& value) {
- if (value == "hello") {
- DCHECK(!perf_logger_.get());
- std::string test_name =
- base::StringPrintf("IPC_%s_Perf_%dx_%zu", label_.c_str(),
- message_count_, payload_.size());
- perf_logger_ = std::make_unique<base::PerfTimeLogger>(test_name.c_str());
- } else {
- DCHECK_EQ(payload_.size(), value.size());
- CHECK(count_down_ > 0);
- count_down_--;
- if (count_down_ == 0) {
- perf_logger_.reset();
- base::RunLoop::QuitCurrentWhenIdleDeprecated();
- return;
- }
- }
- if (sync_) {
- for (int i = 0; i < count_down_; ++i) {
- std::string response;
- ping_receiver_->SyncPing(payload_, &response);
- DCHECK_EQ(response, payload_);
- }
- perf_logger_.reset();
- base::RunLoop::QuitCurrentWhenIdleDeprecated();
- } else {
- ping_receiver_->Ping(payload_,
- base::BindOnce(&MojoInterfacePerfTest::OnPong,
- base::Unretained(this)));
- }
- }
- static int RunPingPongClient(MojoHandle mp) {
- mojo::MessagePipeHandle mp_handle(mp);
- mojo::ScopedMessagePipeHandle scoped_mp(mp_handle);
- LockThreadAffinity thread_locker(kSharedCore);
- // In single process mode, this is running in a task and by default other
- // tasks (in particular, the binding) won't run. To keep the single process
- // and multi-process code paths the same, enable nestable tasks.
- base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed);
- ReflectorImpl impl(std::move(scoped_mp), run_loop.QuitWhenIdleClosure());
- run_loop.Run();
- return 0;
- }
- bool sync_ = false;
- private:
- int message_count_;
- int count_down_;
- std::string label_;
- std::string payload_;
- mojo::Remote<IPC::mojom::Reflector> ping_receiver_;
- std::unique_ptr<base::PerfTimeLogger> perf_logger_;
- };
- class InterfacePassingTestDriverImpl : public mojom::InterfacePassingTestDriver,
- public mojom::PingReceiver {
- public:
- InterfacePassingTestDriverImpl(mojo::ScopedMessagePipeHandle handle,
- base::OnceClosure quit_closure)
- : receiver_(this,
- mojo::PendingReceiver<mojom::InterfacePassingTestDriver>(
- std::move(handle))),
- quit_closure_(std::move(quit_closure)) {}
- ~InterfacePassingTestDriverImpl() override {
- std::ignore = receiver_.Unbind().PassPipe().release();
- }
- private:
- // mojom::InterfacePassingTestDriver implementation:
- void Init(InitCallback callback) override { std::move(callback).Run(); }
- void GetPingReceiver(
- std::vector<mojo::PendingReceiver<mojom::PingReceiver>> receivers,
- GetPingReceiverCallback callback) override {
- for (auto& receiver : receivers)
- ping_receiver_receivers_.Add(this, std::move(receiver));
- ping_receiver_receivers_.Clear();
- std::move(callback).Run();
- }
- void GetAssociatedPingReceiver(
- std::vector<mojo::PendingAssociatedReceiver<mojom::PingReceiver>>
- receivers,
- GetAssociatedPingReceiverCallback callback) override {
- for (auto& receiver : receivers)
- ping_receiver_associated_receivers_.Add(this, std::move(receiver));
- ping_receiver_associated_receivers_.Clear();
- std::move(callback).Run();
- }
- void Quit() override {
- if (quit_closure_)
- std::move(quit_closure_).Run();
- }
- // mojom::PingReceiver implementation:
- void Ping(PingCallback callback) override { std::move(callback).Run(); }
- mojo::ReceiverSet<mojom::PingReceiver> ping_receiver_receivers_;
- mojo::AssociatedReceiverSet<mojom::PingReceiver>
- ping_receiver_associated_receivers_;
- mojo::Receiver<mojom::InterfacePassingTestDriver> receiver_;
- base::OnceClosure quit_closure_;
- };
- class MojoInterfacePassingPerfTest : public mojo::core::test::MojoTestBase {
- public:
- MojoInterfacePassingPerfTest() = default;
- MojoInterfacePassingPerfTest(const MojoInterfacePassingPerfTest&) = delete;
- MojoInterfacePassingPerfTest& operator=(const MojoInterfacePassingPerfTest&) =
- delete;
- protected:
- void RunInterfacePassingServer(MojoHandle mp,
- const std::string& label,
- bool associated) {
- label_ = label;
- associated_ = associated;
- mojo::MessagePipeHandle mp_handle(mp);
- mojo::ScopedMessagePipeHandle scoped_mp(mp_handle);
- driver_remote_.Bind(mojo::PendingRemote<mojom::InterfacePassingTestDriver>(
- std::move(scoped_mp), 0u));
- auto params = GetDefaultInterfacePassingTestParams();
- LockThreadAffinity thread_locker(kSharedCore);
- for (size_t i = 0; i < params.size(); ++i) {
- driver_remote_->Init(
- base::BindOnce(&MojoInterfacePassingPerfTest::OnInitCallback,
- base::Unretained(this)));
- rounds_ = count_down_ = params[i].rounds();
- num_interfaces_ = params[i].num_interfaces();
- base::RunLoop run_loop;
- quit_closure_ = run_loop.QuitWhenIdleClosure();
- run_loop.Run();
- }
- driver_remote_->Quit();
- std::ignore = driver_remote_.Unbind().PassPipe().release();
- }
- void OnInitCallback() {
- DCHECK(!perf_logger_.get());
- std::string test_name = base::StringPrintf(
- "IPC_%s_Perf_%zux_%zu", label_.c_str(), rounds_, num_interfaces_);
- perf_logger_ = std::make_unique<base::PerfTimeLogger>(test_name.c_str());
- DoNextRound();
- }
- void DoNextRound() {
- if (associated_) {
- std::vector<mojo::AssociatedRemote<mojom::PingReceiver>>
- associated_remotes(num_interfaces_);
- std::vector<mojo::PendingAssociatedReceiver<mojom::PingReceiver>>
- receivers(num_interfaces_);
- for (size_t i = 0; i < num_interfaces_; ++i) {
- receivers[i] = associated_remotes[i].BindNewEndpointAndPassReceiver();
- // Force the interface pointer to do full initialization.
- associated_remotes[i].get();
- }
- driver_remote_->GetAssociatedPingReceiver(
- std::move(receivers),
- base::BindOnce(&MojoInterfacePassingPerfTest::OnGetReceiverCallback,
- base::Unretained(this)));
- } else {
- std::vector<mojo::Remote<mojom::PingReceiver>> remotes(num_interfaces_);
- std::vector<mojo::PendingReceiver<mojom::PingReceiver>> receivers(
- num_interfaces_);
- for (size_t i = 0; i < num_interfaces_; ++i) {
- receivers[i] = remotes[i].BindNewPipeAndPassReceiver();
- // Force the interface pointer to do full initialization.
- remotes[i].get();
- }
- driver_remote_->GetPingReceiver(
- std::move(receivers),
- base::BindOnce(&MojoInterfacePassingPerfTest::OnGetReceiverCallback,
- base::Unretained(this)));
- }
- }
- void OnGetReceiverCallback() {
- CHECK_GT(count_down_, 0u);
- count_down_--;
- if (count_down_ == 0) {
- perf_logger_.reset();
- std::move(quit_closure_).Run();
- return;
- }
- DoNextRound();
- }
- static int RunInterfacePassingClient(MojoHandle mp) {
- mojo::MessagePipeHandle mp_handle(mp);
- mojo::ScopedMessagePipeHandle scoped_mp(mp_handle);
- LockThreadAffinity thread_locker(kSharedCore);
- // In single process mode, this is running in a task and by default other
- // tasks (in particular, the binding) won't run. To keep the single process
- // and multi-process code paths the same, enable nestable tasks.
- base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed);
- InterfacePassingTestDriverImpl impl(std::move(scoped_mp),
- run_loop.QuitWhenIdleClosure());
- run_loop.Run();
- return 0;
- }
- private:
- size_t rounds_ = 0;
- size_t count_down_ = 0;
- size_t num_interfaces_ = 0;
- std::string label_;
- bool associated_ = false;
- std::unique_ptr<base::PerfTimeLogger> perf_logger_;
- mojo::Remote<mojom::InterfacePassingTestDriver> driver_remote_;
- base::OnceClosure quit_closure_;
- };
- DEFINE_TEST_CLIENT_WITH_PIPE(InterfacePassingClient,
- MojoInterfacePassingPerfTest,
- h) {
- base::test::SingleThreadTaskEnvironment task_environment;
- return RunInterfacePassingClient(h);
- }
- enum class InProcessMessageMode {
- kSerialized,
- kUnserialized,
- };
- template <class TestBase>
- class InProcessPerfTest
- : public TestBase,
- public testing::WithParamInterface<InProcessMessageMode> {
- public:
- InProcessPerfTest() {
- switch (GetParam()) {
- case InProcessMessageMode::kSerialized:
- mojo::Connector::OverrideDefaultSerializationBehaviorForTesting(
- mojo::Connector::OutgoingSerializationMode::kEager,
- mojo::Connector::IncomingSerializationMode::kDispatchAsIs);
- break;
- case InProcessMessageMode::kUnserialized:
- mojo::Connector::OverrideDefaultSerializationBehaviorForTesting(
- mojo::Connector::OutgoingSerializationMode::kLazy,
- mojo::Connector::IncomingSerializationMode::kDispatchAsIs);
- break;
- }
- }
- };
- using MojoInProcessInterfacePerfTest = InProcessPerfTest<MojoInterfacePerfTest>;
- using MojoInProcessInterfacePassingPerfTest =
- InProcessPerfTest<MojoInterfacePassingPerfTest>;
- DEFINE_TEST_CLIENT_WITH_PIPE(PingPongClient, MojoInterfacePerfTest, h) {
- base::test::SingleThreadTaskEnvironment task_environment;
- return RunPingPongClient(h);
- }
- // Similar to MojoChannelPerfTest above, but uses a Mojo interface instead of
- // raw IPC::Messages.
- TEST_F(MojoInterfacePerfTest, MultiprocessPingPong) {
- RunTestClient("PingPongClient", [&](MojoHandle h) {
- base::test::SingleThreadTaskEnvironment task_environment;
- RunPingPongServer(h, "Multiprocess");
- });
- }
- TEST_F(MojoInterfacePerfTest, MultiprocessSyncPing) {
- sync_ = true;
- RunTestClient("PingPongClient", [&](MojoHandle h) {
- base::test::SingleThreadTaskEnvironment task_environment;
- RunPingPongServer(h, "MultiprocessSync");
- });
- }
- TEST_F(MojoInterfacePassingPerfTest, MultiprocessInterfacePassing) {
- RunTestClient("InterfacePassingClient", [&](MojoHandle h) {
- base::test::SingleThreadTaskEnvironment task_environment;
- RunInterfacePassingServer(h, "InterfacePassing", false /* associated */);
- });
- }
- TEST_F(MojoInterfacePassingPerfTest, MultiprocessAssociatedInterfacePassing) {
- RunTestClient("InterfacePassingClient", [&](MojoHandle h) {
- base::test::SingleThreadTaskEnvironment task_environment;
- RunInterfacePassingServer(h, "AssociatedInterfacePassing",
- true /* associated*/);
- });
- }
- // A single process version of the above test.
- TEST_P(MojoInProcessInterfacePerfTest, MultiThreadPingPong) {
- MojoHandle server_handle, client_handle;
- CreateMessagePipe(&server_handle, &client_handle);
- base::Thread client_thread("PingPongClient");
- client_thread.Start();
- client_thread.task_runner()->PostTask(
- FROM_HERE,
- base::BindOnce(base::IgnoreResult(&RunPingPongClient), client_handle));
- base::test::SingleThreadTaskEnvironment task_environment;
- RunPingPongServer(server_handle, "SingleProcess");
- }
- TEST_P(MojoInProcessInterfacePerfTest, SingleThreadPingPong) {
- MojoHandle server_handle, client_handle;
- CreateMessagePipe(&server_handle, &client_handle);
- base::test::SingleThreadTaskEnvironment task_environment;
- mojo::MessagePipeHandle mp_handle(client_handle);
- mojo::ScopedMessagePipeHandle scoped_mp(mp_handle);
- LockThreadAffinity thread_locker(kSharedCore);
- ReflectorImpl impl(std::move(scoped_mp), base::OnceClosure());
- RunPingPongServer(server_handle, "SingleProcess");
- }
- INSTANTIATE_TEST_SUITE_P(All,
- MojoInProcessInterfacePerfTest,
- testing::Values(InProcessMessageMode::kSerialized,
- InProcessMessageMode::kUnserialized));
- TEST_P(MojoInProcessInterfacePassingPerfTest, MultiThreadInterfacePassing) {
- MojoHandle server_handle, client_handle;
- CreateMessagePipe(&server_handle, &client_handle);
- base::Thread client_thread("InterfacePassingClient");
- client_thread.Start();
- client_thread.task_runner()->PostTask(
- FROM_HERE, base::BindOnce(base::IgnoreResult(&RunInterfacePassingClient),
- client_handle));
- base::test::SingleThreadTaskEnvironment task_environment;
- RunInterfacePassingServer(server_handle, "SingleProcess",
- false /* associated */);
- }
- TEST_P(MojoInProcessInterfacePassingPerfTest,
- MultiThreadAssociatedInterfacePassing) {
- MojoHandle server_handle, client_handle;
- CreateMessagePipe(&server_handle, &client_handle);
- base::Thread client_thread("InterfacePassingClient");
- client_thread.Start();
- client_thread.task_runner()->PostTask(
- FROM_HERE, base::BindOnce(base::IgnoreResult(&RunInterfacePassingClient),
- client_handle));
- base::test::SingleThreadTaskEnvironment task_environment;
- RunInterfacePassingServer(server_handle, "SingleProcess",
- true /* associated */);
- }
- TEST_P(MojoInProcessInterfacePassingPerfTest, SingleThreadInterfacePassing) {
- MojoHandle server_handle, client_handle;
- CreateMessagePipe(&server_handle, &client_handle);
- base::test::SingleThreadTaskEnvironment task_environment;
- mojo::MessagePipeHandle mp_handle(client_handle);
- mojo::ScopedMessagePipeHandle scoped_mp(mp_handle);
- LockThreadAffinity thread_locker(kSharedCore);
- InterfacePassingTestDriverImpl impl(std::move(scoped_mp),
- base::OnceClosure());
- RunInterfacePassingServer(server_handle, "SingleProcess",
- false /* associated */);
- }
- TEST_P(MojoInProcessInterfacePassingPerfTest,
- SingleThreadAssociatedInterfacePassing) {
- MojoHandle server_handle, client_handle;
- CreateMessagePipe(&server_handle, &client_handle);
- base::test::SingleThreadTaskEnvironment task_environment;
- mojo::MessagePipeHandle mp_handle(client_handle);
- mojo::ScopedMessagePipeHandle scoped_mp(mp_handle);
- LockThreadAffinity thread_locker(kSharedCore);
- InterfacePassingTestDriverImpl impl(std::move(scoped_mp),
- base::OnceClosure());
- RunInterfacePassingServer(server_handle, "SingleProcess",
- true /* associated */);
- }
- INSTANTIATE_TEST_SUITE_P(All,
- MojoInProcessInterfacePassingPerfTest,
- testing::Values(InProcessMessageMode::kSerialized,
- InProcessMessageMode::kUnserialized));
- class CallbackPerfTest : public testing::Test {
- public:
- CallbackPerfTest()
- : client_thread_("PingPongClient"), message_count_(0), count_down_(0) {}
- CallbackPerfTest(const CallbackPerfTest&) = delete;
- CallbackPerfTest& operator=(const CallbackPerfTest&) = delete;
- protected:
- void RunMultiThreadPingPongServer() {
- client_thread_.Start();
- LockThreadAffinity thread_locker(kSharedCore);
- std::vector<PingPongTestParams> params = GetDefaultTestParams();
- for (size_t i = 0; i < params.size(); i++) {
- std::string hello("hello");
- client_thread_.task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&CallbackPerfTest::Ping,
- base::Unretained(this), hello));
- message_count_ = count_down_ = params[i].message_count();
- payload_ = std::string(params[i].message_size(), 'a');
- base::RunLoop().Run();
- }
- }
- void Ping(const std::string& value) {
- task_environment_.GetMainThreadTaskRunner()->PostTask(
- FROM_HERE, base::BindOnce(&CallbackPerfTest::OnPong,
- base::Unretained(this), value));
- }
- void OnPong(const std::string& value) {
- if (value == "hello") {
- DCHECK(!perf_logger_.get());
- std::string test_name =
- base::StringPrintf("Callback_MultiProcess_Perf_%dx_%zu",
- message_count_, payload_.size());
- perf_logger_ = std::make_unique<base::PerfTimeLogger>(test_name.c_str());
- } else {
- DCHECK_EQ(payload_.size(), value.size());
- CHECK(count_down_ > 0);
- count_down_--;
- if (count_down_ == 0) {
- perf_logger_.reset();
- base::RunLoop::QuitCurrentWhenIdleDeprecated();
- return;
- }
- }
- client_thread_.task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&CallbackPerfTest::Ping,
- base::Unretained(this), payload_));
- }
- void RunSingleThreadNoPostTaskPingPongServer() {
- LockThreadAffinity thread_locker(kSharedCore);
- std::vector<PingPongTestParams> params = GetDefaultTestParams();
- base::RepeatingCallback<void(
- const std::string&, int,
- base::OnceCallback<void(const std::string&, int)>)>
- ping =
- base::BindRepeating(&CallbackPerfTest::SingleThreadPingNoPostTask,
- base::Unretained(this));
- for (size_t i = 0; i < params.size(); i++) {
- payload_ = std::string(params[i].message_size(), 'a');
- std::string test_name =
- base::StringPrintf("Callback_SingleThreadNoPostTask_Perf_%dx_%zu",
- params[i].message_count(), payload_.size());
- perf_logger_ = std::make_unique<base::PerfTimeLogger>(test_name.c_str());
- for (int j = 0; j < params[i].message_count(); ++j) {
- ping.Run(payload_, j,
- base::BindOnce(&CallbackPerfTest::SingleThreadPongNoPostTask,
- base::Unretained(this)));
- }
- perf_logger_.reset();
- }
- }
- void SingleThreadPingNoPostTask(
- const std::string& value,
- int i,
- base::OnceCallback<void(const std::string&, int)> pong) {
- std::move(pong).Run(value, i);
- }
- void SingleThreadPongNoPostTask(const std::string& value, int i) {}
- void RunSingleThreadPostTaskPingPongServer() {
- LockThreadAffinity thread_locker(kSharedCore);
- std::vector<PingPongTestParams> params = GetDefaultTestParams();
- for (size_t i = 0; i < params.size(); i++) {
- std::string hello("hello");
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(&CallbackPerfTest::SingleThreadPingPostTask,
- base::Unretained(this), hello));
- message_count_ = count_down_ = params[i].message_count();
- payload_ = std::string(params[i].message_size(), 'a');
- base::RunLoop().Run();
- }
- }
- void SingleThreadPingPostTask(const std::string& value) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(&CallbackPerfTest::SingleThreadPongPostTask,
- base::Unretained(this), value));
- }
- void SingleThreadPongPostTask(const std::string& value) {
- if (value == "hello") {
- DCHECK(!perf_logger_.get());
- std::string test_name =
- base::StringPrintf("Callback_SingleThreadPostTask_Perf_%dx_%zu",
- message_count_, payload_.size());
- perf_logger_ = std::make_unique<base::PerfTimeLogger>(test_name.c_str());
- } else {
- DCHECK_EQ(payload_.size(), value.size());
- CHECK(count_down_ > 0);
- count_down_--;
- if (count_down_ == 0) {
- perf_logger_.reset();
- base::RunLoop::QuitCurrentWhenIdleDeprecated();
- return;
- }
- }
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(&CallbackPerfTest::SingleThreadPingPostTask,
- base::Unretained(this), payload_));
- }
- private:
- base::Thread client_thread_;
- base::test::SingleThreadTaskEnvironment task_environment_;
- int message_count_;
- int count_down_;
- std::string payload_;
- std::unique_ptr<base::PerfTimeLogger> perf_logger_;
- };
- // Sends the same data as above using PostTask to a different thread instead of
- // IPCs for comparison.
- TEST_F(CallbackPerfTest, MultiThreadPingPong) {
- RunMultiThreadPingPongServer();
- }
- // Sends the same data as above using PostTask to the same thread.
- TEST_F(CallbackPerfTest, SingleThreadPostTaskPingPong) {
- RunSingleThreadPostTaskPingPongServer();
- }
- // Sends the same data as above without using PostTask to the same thread.
- TEST_F(CallbackPerfTest, SingleThreadNoPostTaskPingPong) {
- RunSingleThreadNoPostTaskPingPongServer();
- }
- } // namespace
- } // namespace IPC
|