207 lines
6.3 KiB
C++
207 lines
6.3 KiB
C++
// Copyright 2016 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 <string>
|
|
#include <utility>
|
|
|
|
#include "base/bind.h"
|
|
#include "base/callback.h"
|
|
#include "base/memory/ptr_util.h"
|
|
#include "base/message_loop/message_loop.h"
|
|
#include "base/message_loop/message_loop_current.h"
|
|
#include "base/run_loop.h"
|
|
#include "base/strings/stringprintf.h"
|
|
#include "base/test/perf_time_logger.h"
|
|
#include "base/threading/thread_task_runner_handle.h"
|
|
#include "mojo/core/embedder/embedder.h"
|
|
#include "mojo/core/test/mojo_test_base.h"
|
|
#include "mojo/public/cpp/bindings/strong_binding.h"
|
|
#include "mojo/public/interfaces/bindings/tests/ping_service.mojom.h"
|
|
#include "testing/gtest/include/gtest/gtest.h"
|
|
|
|
namespace mojo {
|
|
namespace {
|
|
|
|
class EchoServiceImpl : public test::EchoService {
|
|
public:
|
|
explicit EchoServiceImpl(const base::Closure& quit_closure);
|
|
~EchoServiceImpl() override;
|
|
|
|
// |EchoService| methods:
|
|
void Echo(const std::string& test_data,
|
|
const EchoCallback& callback) override;
|
|
|
|
private:
|
|
const base::Closure quit_closure_;
|
|
};
|
|
|
|
EchoServiceImpl::EchoServiceImpl(const base::Closure& quit_closure)
|
|
: quit_closure_(quit_closure) {}
|
|
|
|
EchoServiceImpl::~EchoServiceImpl() {
|
|
quit_closure_.Run();
|
|
}
|
|
|
|
void EchoServiceImpl::Echo(const std::string& test_data,
|
|
const EchoCallback& callback) {
|
|
callback.Run(test_data);
|
|
}
|
|
|
|
class PingPongTest {
|
|
public:
|
|
explicit PingPongTest(test::EchoServicePtr service);
|
|
|
|
void RunTest(int iterations, int batch_size, int message_size);
|
|
|
|
private:
|
|
void DoPing();
|
|
void OnPingDone(const std::string& reply);
|
|
|
|
test::EchoServicePtr service_;
|
|
const base::Callback<void(const std::string&)> ping_done_callback_;
|
|
|
|
int iterations_;
|
|
int batch_size_;
|
|
std::string message_;
|
|
|
|
int current_iterations_;
|
|
int calls_outstanding_;
|
|
|
|
base::Closure quit_closure_;
|
|
};
|
|
|
|
PingPongTest::PingPongTest(test::EchoServicePtr service)
|
|
: service_(std::move(service)),
|
|
ping_done_callback_(
|
|
base::Bind(&PingPongTest::OnPingDone, base::Unretained(this))) {}
|
|
|
|
void PingPongTest::RunTest(int iterations, int batch_size, int message_size) {
|
|
iterations_ = iterations;
|
|
batch_size_ = batch_size;
|
|
message_ = std::string(message_size, 'a');
|
|
current_iterations_ = 0;
|
|
calls_outstanding_ = 0;
|
|
|
|
base::MessageLoopCurrent::Get()->SetNestableTasksAllowed(true);
|
|
base::RunLoop run_loop;
|
|
quit_closure_ = run_loop.QuitClosure();
|
|
base::ThreadTaskRunnerHandle::Get()->PostTask(
|
|
FROM_HERE, base::Bind(&PingPongTest::DoPing, base::Unretained(this)));
|
|
run_loop.Run();
|
|
}
|
|
|
|
void PingPongTest::DoPing() {
|
|
DCHECK_EQ(0, calls_outstanding_);
|
|
current_iterations_++;
|
|
if (current_iterations_ > iterations_) {
|
|
quit_closure_.Run();
|
|
return;
|
|
}
|
|
|
|
calls_outstanding_ = batch_size_;
|
|
for (int i = 0; i < batch_size_; i++) {
|
|
service_->Echo(message_, ping_done_callback_);
|
|
}
|
|
}
|
|
|
|
void PingPongTest::OnPingDone(const std::string& reply) {
|
|
DCHECK_GT(calls_outstanding_, 0);
|
|
calls_outstanding_--;
|
|
|
|
if (!calls_outstanding_)
|
|
DoPing();
|
|
}
|
|
|
|
class MojoE2EPerftest : public core::test::MojoTestBase {
|
|
public:
|
|
void RunTestOnTaskRunner(base::TaskRunner* runner,
|
|
MojoHandle client_mp,
|
|
const std::string& test_name) {
|
|
if (runner == base::ThreadTaskRunnerHandle::Get().get()) {
|
|
RunTests(client_mp, test_name);
|
|
} else {
|
|
base::RunLoop run_loop;
|
|
runner->PostTaskAndReply(
|
|
FROM_HERE,
|
|
base::Bind(&MojoE2EPerftest::RunTests, base::Unretained(this),
|
|
client_mp, test_name),
|
|
run_loop.QuitClosure());
|
|
run_loop.Run();
|
|
}
|
|
}
|
|
|
|
protected:
|
|
base::MessageLoop message_loop_;
|
|
|
|
private:
|
|
void RunTests(MojoHandle client_mp, const std::string& test_name) {
|
|
const int kMessages = 10000;
|
|
const int kBatchSizes[] = {1, 10, 100};
|
|
const int kMessageSizes[] = {8, 64, 512, 4096, 65536};
|
|
|
|
test::EchoServicePtr service;
|
|
service.Bind(InterfacePtrInfo<test::EchoService>(
|
|
ScopedMessagePipeHandle(MessagePipeHandle(client_mp)),
|
|
service.version()));
|
|
PingPongTest test(std::move(service));
|
|
|
|
for (int batch_size : kBatchSizes) {
|
|
for (int message_size : kMessageSizes) {
|
|
int num_messages = kMessages;
|
|
if (message_size == 65536)
|
|
num_messages /= 10;
|
|
std::string sub_test_name = base::StringPrintf(
|
|
"%s/%dx%d/%dbytes", test_name.c_str(), num_messages / batch_size,
|
|
batch_size, message_size);
|
|
base::PerfTimeLogger timer(sub_test_name.c_str());
|
|
test.RunTest(num_messages / batch_size, batch_size, message_size);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
void CreateAndRunService(InterfaceRequest<test::EchoService> request,
|
|
const base::Closure& cb) {
|
|
MakeStrongBinding(std::make_unique<EchoServiceImpl>(cb), std::move(request));
|
|
}
|
|
|
|
DEFINE_TEST_CLIENT_TEST_WITH_PIPE(PingService, MojoE2EPerftest, mp) {
|
|
MojoHandle service_mp;
|
|
EXPECT_EQ("hello", ReadMessageWithHandles(mp, &service_mp, 1));
|
|
|
|
auto request = InterfaceRequest<test::EchoService>(
|
|
ScopedMessagePipeHandle(MessagePipeHandle(service_mp)));
|
|
base::RunLoop run_loop;
|
|
core::GetIOTaskRunner()->PostTask(
|
|
FROM_HERE,
|
|
base::Bind(&CreateAndRunService, base::Passed(&request),
|
|
base::Bind(base::IgnoreResult(&base::TaskRunner::PostTask),
|
|
message_loop_.task_runner(), FROM_HERE,
|
|
run_loop.QuitClosure())));
|
|
run_loop.Run();
|
|
}
|
|
|
|
TEST_F(MojoE2EPerftest, MultiProcessEchoMainThread) {
|
|
RunTestClient("PingService", [&](MojoHandle mp) {
|
|
MojoHandle client_mp, service_mp;
|
|
CreateMessagePipe(&client_mp, &service_mp);
|
|
WriteMessageWithHandles(mp, "hello", &service_mp, 1);
|
|
RunTestOnTaskRunner(message_loop_.task_runner().get(), client_mp,
|
|
"MultiProcessEchoMainThread");
|
|
});
|
|
}
|
|
|
|
TEST_F(MojoE2EPerftest, MultiProcessEchoIoThread) {
|
|
RunTestClient("PingService", [&](MojoHandle mp) {
|
|
MojoHandle client_mp, service_mp;
|
|
CreateMessagePipe(&client_mp, &service_mp);
|
|
WriteMessageWithHandles(mp, "hello", &service_mp, 1);
|
|
RunTestOnTaskRunner(core::GetIOTaskRunner().get(), client_mp,
|
|
"MultiProcessEchoIoThread");
|
|
});
|
|
}
|
|
|
|
} // namespace
|
|
} // namespace mojo
|