You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
865 lines
28 KiB
865 lines
28 KiB
// 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 "base/memory/ptr_util.h"
|
|
#include "base/message_loop/message_loop.h"
|
|
#include "base/message_loop/message_loop_current.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/threading/thread.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_binding_set.h"
|
|
#include "mojo/public/cpp/bindings/binding.h"
|
|
#include "mojo/public/cpp/bindings/binding_set.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_(NULL),
|
|
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_.reset(new 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_;
|
|
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::Bind(&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) {}
|
|
|
|
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(IPC::mojom::ReflectorPtrInfo(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::Bind(&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();
|
|
|
|
ignore_result(ping_receiver_.PassInterface().PassHandle().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_.reset(new 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::Bind(&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_;
|
|
IPC::mojom::ReflectorPtr ping_receiver_;
|
|
std::unique_ptr<base::PerfTimeLogger> perf_logger_;
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(MojoInterfacePerfTest);
|
|
};
|
|
|
|
class InterfacePassingTestDriverImpl : public mojom::InterfacePassingTestDriver,
|
|
public mojom::PingReceiver {
|
|
public:
|
|
InterfacePassingTestDriverImpl(mojo::ScopedMessagePipeHandle handle,
|
|
const base::Closure& quit_closure)
|
|
: binding_(this,
|
|
mojom::InterfacePassingTestDriverRequest(std::move(handle))),
|
|
quit_closure_(quit_closure) {}
|
|
~InterfacePassingTestDriverImpl() override {
|
|
ignore_result(binding_.Unbind().PassMessagePipe().release());
|
|
}
|
|
|
|
private:
|
|
// mojom::InterfacePassingTestDriver implementation:
|
|
void Init(InitCallback callback) override { std::move(callback).Run(); }
|
|
|
|
void GetPingReceiver(std::vector<mojom::PingReceiverRequest> requests,
|
|
GetPingReceiverCallback callback) override {
|
|
for (auto& request : requests)
|
|
ping_receiver_bindings_.AddBinding(this, std::move(request));
|
|
ping_receiver_bindings_.CloseAllBindings();
|
|
std::move(callback).Run();
|
|
}
|
|
|
|
void GetAssociatedPingReceiver(
|
|
std::vector<mojom::PingReceiverAssociatedRequest> requests,
|
|
GetAssociatedPingReceiverCallback callback) override {
|
|
for (auto& request : requests)
|
|
ping_receiver_associated_bindings_.AddBinding(this, std::move(request));
|
|
ping_receiver_associated_bindings_.CloseAllBindings();
|
|
std::move(callback).Run();
|
|
}
|
|
|
|
void Quit() override {
|
|
if (quit_closure_)
|
|
quit_closure_.Run();
|
|
}
|
|
|
|
// mojom::PingReceiver implementation:
|
|
void Ping(PingCallback callback) override { std::move(callback).Run(); }
|
|
|
|
mojo::BindingSet<mojom::PingReceiver> ping_receiver_bindings_;
|
|
mojo::AssociatedBindingSet<mojom::PingReceiver>
|
|
ping_receiver_associated_bindings_;
|
|
mojo::Binding<mojom::InterfacePassingTestDriver> binding_;
|
|
|
|
base::Closure quit_closure_;
|
|
};
|
|
|
|
class MojoInterfacePassingPerfTest : public mojo::core::test::MojoTestBase {
|
|
public:
|
|
MojoInterfacePassingPerfTest() = default;
|
|
|
|
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_ptr_.Bind(
|
|
mojom::InterfacePassingTestDriverPtrInfo(std::move(scoped_mp), 0u));
|
|
|
|
auto params = GetDefaultInterfacePassingTestParams();
|
|
|
|
LockThreadAffinity thread_locker(kSharedCore);
|
|
for (size_t i = 0; i < params.size(); ++i) {
|
|
driver_ptr_->Init(
|
|
base::Bind(&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_ptr_->Quit();
|
|
|
|
ignore_result(driver_ptr_.PassInterface().PassHandle().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_.reset(new base::PerfTimeLogger(test_name.c_str()));
|
|
|
|
DoNextRound();
|
|
}
|
|
|
|
void DoNextRound() {
|
|
if (associated_) {
|
|
std::vector<mojom::PingReceiverAssociatedPtr> associated_interfaces(
|
|
num_interfaces_);
|
|
|
|
std::vector<mojom::PingReceiverAssociatedRequest> requests(
|
|
num_interfaces_);
|
|
for (size_t i = 0; i < num_interfaces_; ++i) {
|
|
requests[i] = mojo::MakeRequest(&associated_interfaces[i]);
|
|
// Force the interface pointer to do full initialization.
|
|
associated_interfaces[i].get();
|
|
}
|
|
|
|
driver_ptr_->GetAssociatedPingReceiver(
|
|
std::move(requests),
|
|
base::Bind(&MojoInterfacePassingPerfTest::OnGetReceiverCallback,
|
|
base::Unretained(this)));
|
|
} else {
|
|
std::vector<mojom::PingReceiverPtr> interfaces(num_interfaces_);
|
|
|
|
std::vector<mojom::PingReceiverRequest> requests(num_interfaces_);
|
|
for (size_t i = 0; i < num_interfaces_; ++i) {
|
|
requests[i] = mojo::MakeRequest(&interfaces[i]);
|
|
// Force the interface pointer to do full initialization.
|
|
interfaces[i].get();
|
|
}
|
|
|
|
driver_ptr_->GetPingReceiver(
|
|
std::move(requests),
|
|
base::Bind(&MojoInterfacePassingPerfTest::OnGetReceiverCallback,
|
|
base::Unretained(this)));
|
|
}
|
|
}
|
|
|
|
void OnGetReceiverCallback() {
|
|
CHECK_GT(count_down_, 0u);
|
|
count_down_--;
|
|
|
|
if (count_down_ == 0) {
|
|
perf_logger_.reset();
|
|
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_;
|
|
|
|
mojom::InterfacePassingTestDriverPtr driver_ptr_;
|
|
|
|
base::Closure quit_closure_;
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(MojoInterfacePassingPerfTest);
|
|
};
|
|
|
|
DEFINE_TEST_CLIENT_WITH_PIPE(InterfacePassingClient,
|
|
MojoInterfacePassingPerfTest,
|
|
h) {
|
|
base::MessageLoop main_message_loop;
|
|
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::MessageLoop main_message_loop;
|
|
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::MessageLoop main_message_loop;
|
|
RunPingPongServer(h, "Multiprocess");
|
|
});
|
|
}
|
|
|
|
TEST_F(MojoInterfacePerfTest, MultiprocessSyncPing) {
|
|
sync_ = true;
|
|
RunTestClient("PingPongClient", [&](MojoHandle h) {
|
|
base::MessageLoop main_message_loop;
|
|
RunPingPongServer(h, "MultiprocessSync");
|
|
});
|
|
}
|
|
|
|
TEST_F(MojoInterfacePassingPerfTest, MultiprocessInterfacePassing) {
|
|
RunTestClient("InterfacePassingClient", [&](MojoHandle h) {
|
|
base::MessageLoop main_message_loop;
|
|
RunInterfacePassingServer(h, "InterfacePassing", false /* associated */);
|
|
});
|
|
}
|
|
|
|
TEST_F(MojoInterfacePassingPerfTest, MultiprocessAssociatedInterfacePassing) {
|
|
RunTestClient("InterfacePassingClient", [&](MojoHandle h) {
|
|
base::MessageLoop main_message_loop;
|
|
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::Bind(base::IgnoreResult(&RunPingPongClient), client_handle));
|
|
|
|
base::MessageLoop main_message_loop;
|
|
RunPingPongServer(server_handle, "SingleProcess");
|
|
}
|
|
|
|
TEST_P(MojoInProcessInterfacePerfTest, SingleThreadPingPong) {
|
|
MojoHandle server_handle, client_handle;
|
|
CreateMessagePipe(&server_handle, &client_handle);
|
|
|
|
base::MessageLoop main_message_loop;
|
|
mojo::MessagePipeHandle mp_handle(client_handle);
|
|
mojo::ScopedMessagePipeHandle scoped_mp(mp_handle);
|
|
LockThreadAffinity thread_locker(kSharedCore);
|
|
ReflectorImpl impl(std::move(scoped_mp), base::Closure());
|
|
|
|
RunPingPongServer(server_handle, "SingleProcess");
|
|
}
|
|
|
|
INSTANTIATE_TEST_CASE_P(,
|
|
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::Bind(base::IgnoreResult(&RunInterfacePassingClient),
|
|
client_handle));
|
|
|
|
base::MessageLoop main_message_loop;
|
|
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::Bind(base::IgnoreResult(&RunInterfacePassingClient),
|
|
client_handle));
|
|
|
|
base::MessageLoop main_message_loop;
|
|
RunInterfacePassingServer(server_handle, "SingleProcess",
|
|
true /* associated */);
|
|
}
|
|
|
|
TEST_P(MojoInProcessInterfacePassingPerfTest, SingleThreadInterfacePassing) {
|
|
MojoHandle server_handle, client_handle;
|
|
CreateMessagePipe(&server_handle, &client_handle);
|
|
|
|
base::MessageLoop main_message_loop;
|
|
mojo::MessagePipeHandle mp_handle(client_handle);
|
|
mojo::ScopedMessagePipeHandle scoped_mp(mp_handle);
|
|
LockThreadAffinity thread_locker(kSharedCore);
|
|
InterfacePassingTestDriverImpl impl(std::move(scoped_mp), base::Closure());
|
|
|
|
RunInterfacePassingServer(server_handle, "SingleProcess",
|
|
false /* associated */);
|
|
}
|
|
|
|
TEST_P(MojoInProcessInterfacePassingPerfTest,
|
|
SingleThreadAssociatedInterfacePassing) {
|
|
MojoHandle server_handle, client_handle;
|
|
CreateMessagePipe(&server_handle, &client_handle);
|
|
|
|
base::MessageLoop main_message_loop;
|
|
mojo::MessagePipeHandle mp_handle(client_handle);
|
|
mojo::ScopedMessagePipeHandle scoped_mp(mp_handle);
|
|
LockThreadAffinity thread_locker(kSharedCore);
|
|
InterfacePassingTestDriverImpl impl(std::move(scoped_mp), base::Closure());
|
|
|
|
RunInterfacePassingServer(server_handle, "SingleProcess",
|
|
true /* associated */);
|
|
}
|
|
|
|
INSTANTIATE_TEST_CASE_P(,
|
|
MojoInProcessInterfacePassingPerfTest,
|
|
testing::Values(InProcessMessageMode::kSerialized,
|
|
InProcessMessageMode::kUnserialized));
|
|
|
|
class CallbackPerfTest : public testing::Test {
|
|
public:
|
|
CallbackPerfTest()
|
|
: client_thread_("PingPongClient"), message_count_(0), count_down_(0) {}
|
|
|
|
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::Bind(&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) {
|
|
main_message_loop_.task_runner()->PostTask(
|
|
FROM_HERE,
|
|
base::Bind(&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_.reset(new 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::Bind(&CallbackPerfTest::Ping, base::Unretained(this), payload_));
|
|
}
|
|
|
|
void RunSingleThreadNoPostTaskPingPongServer() {
|
|
LockThreadAffinity thread_locker(kSharedCore);
|
|
std::vector<PingPongTestParams> params = GetDefaultTestParams();
|
|
base::Callback<void(const std::string&, int,
|
|
const base::Callback<void(const std::string&, int)>&)>
|
|
ping = base::Bind(&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_.reset(new base::PerfTimeLogger(test_name.c_str()));
|
|
for (int j = 0; j < params[i].message_count(); ++j) {
|
|
ping.Run(payload_, j,
|
|
base::Bind(&CallbackPerfTest::SingleThreadPongNoPostTask,
|
|
base::Unretained(this)));
|
|
}
|
|
perf_logger_.reset();
|
|
}
|
|
}
|
|
|
|
void SingleThreadPingNoPostTask(
|
|
const std::string& value,
|
|
int i,
|
|
const base::Callback<void(const std::string&, int)>& pong) {
|
|
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::MessageLoopCurrent::Get()->task_runner()->PostTask(
|
|
FROM_HERE, base::Bind(&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::MessageLoopCurrent::Get()->task_runner()->PostTask(
|
|
FROM_HERE, base::Bind(&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_.reset(new 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::MessageLoopCurrent::Get()->task_runner()->PostTask(
|
|
FROM_HERE, base::Bind(&CallbackPerfTest::SingleThreadPingPostTask,
|
|
base::Unretained(this), payload_));
|
|
}
|
|
|
|
private:
|
|
base::Thread client_thread_;
|
|
base::MessageLoop main_message_loop_;
|
|
int message_count_;
|
|
int count_down_;
|
|
std::string payload_;
|
|
std::unique_ptr<base::PerfTimeLogger> perf_logger_;
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(CallbackPerfTest);
|
|
};
|
|
|
|
// 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
|