| Index: ipc/ipc_perftest_support.cc
|
| diff --git a/ipc/ipc_perftest_support.cc b/ipc/ipc_perftest_support.cc
|
| deleted file mode 100644
|
| index 10516bc7a1bc45a24d9340b042b6fe6f557a4838..0000000000000000000000000000000000000000
|
| --- a/ipc/ipc_perftest_support.cc
|
| +++ /dev/null
|
| @@ -1,396 +0,0 @@
|
| -// Copyright (c) 2012 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 "ipc/ipc_perftest_support.h"
|
| -
|
| -#include <stddef.h>
|
| -#include <stdint.h>
|
| -
|
| -#include <algorithm>
|
| -#include <memory>
|
| -#include <string>
|
| -
|
| -#include "base/logging.h"
|
| -#include "base/macros.h"
|
| -#include "base/memory/ptr_util.h"
|
| -#include "base/pickle.h"
|
| -#include "base/run_loop.h"
|
| -#include "base/strings/stringprintf.h"
|
| -#include "base/test/perf_time_logger.h"
|
| -#include "base/test/test_io_thread.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.h"
|
| -#include "ipc/ipc_channel_proxy.h"
|
| -#include "ipc/ipc_descriptors.h"
|
| -#include "ipc/ipc_message_utils.h"
|
| -#include "ipc/ipc_sender.h"
|
| -#include "mojo/edk/test/scoped_ipc_support.h"
|
| -
|
| -namespace IPC {
|
| -namespace test {
|
| -
|
| -// Avoid core 0 due to conflicts with Intel's Power Gadget.
|
| -// Setting thread affinity will fail harmlessly on single/dual core machines.
|
| -const int kSharedCore = 2;
|
| -
|
| -// This class simply collects stats about abstract "events" (each of which has a
|
| -// start time and an end time).
|
| -class EventTimeTracker {
|
| - public:
|
| - explicit EventTimeTracker(const char* name)
|
| - : name_(name),
|
| - count_(0) {
|
| - }
|
| -
|
| - void AddEvent(const base::TimeTicks& start, const base::TimeTicks& end) {
|
| - DCHECK(end >= start);
|
| - count_++;
|
| - base::TimeDelta duration = end - start;
|
| - total_duration_ += duration;
|
| - max_duration_ = std::max(max_duration_, duration);
|
| - }
|
| -
|
| - void ShowResults() const {
|
| - VLOG(1) << name_ << " count: " << count_;
|
| - VLOG(1) << name_ << " total duration: "
|
| - << total_duration_.InMillisecondsF() << " ms";
|
| - VLOG(1) << name_ << " average duration: "
|
| - << (total_duration_.InMillisecondsF() / static_cast<double>(count_))
|
| - << " ms";
|
| - VLOG(1) << name_ << " maximum duration: "
|
| - << max_duration_.InMillisecondsF() << " ms";
|
| - }
|
| -
|
| - void Reset() {
|
| - count_ = 0;
|
| - total_duration_ = base::TimeDelta();
|
| - max_duration_ = base::TimeDelta();
|
| - }
|
| -
|
| - private:
|
| - const std::string name_;
|
| -
|
| - uint64_t count_;
|
| - base::TimeDelta total_duration_;
|
| - base::TimeDelta max_duration_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(EventTimeTracker);
|
| -};
|
| -
|
| -// This channel listener just replies to all messages with the exact same
|
| -// message. It assumes each message has one string parameter. When the string
|
| -// "quit" is sent, it will exit.
|
| -class ChannelReflectorListener : public Listener {
|
| - public:
|
| - ChannelReflectorListener()
|
| - : channel_(NULL),
|
| - latency_tracker_("Client messages") {
|
| - VLOG(1) << "Client listener up";
|
| - }
|
| -
|
| - ~ChannelReflectorListener() override {
|
| - VLOG(1) << "Client listener down";
|
| - latency_tracker_.ShowResults();
|
| - }
|
| -
|
| - void Init(Channel* channel) {
|
| - DCHECK(!channel_);
|
| - channel_ = channel;
|
| - }
|
| -
|
| - bool OnMessageReceived(const Message& message) override {
|
| - CHECK(channel_);
|
| -
|
| - base::PickleIterator iter(message);
|
| - int64_t time_internal;
|
| - EXPECT_TRUE(iter.ReadInt64(&time_internal));
|
| - int msgid;
|
| - EXPECT_TRUE(iter.ReadInt(&msgid));
|
| - base::StringPiece payload;
|
| - EXPECT_TRUE(iter.ReadStringPiece(&payload));
|
| -
|
| - // Include message deserialization in latency.
|
| - base::TimeTicks now = base::TimeTicks::Now();
|
| -
|
| - if (payload == "hello") {
|
| - latency_tracker_.Reset();
|
| - } else if (payload == "quit") {
|
| - latency_tracker_.ShowResults();
|
| - base::MessageLoop::current()->QuitWhenIdle();
|
| - return true;
|
| - } else {
|
| - // Don't track hello and quit messages.
|
| - latency_tracker_.AddEvent(
|
| - base::TimeTicks::FromInternalValue(time_internal), now);
|
| - }
|
| -
|
| - Message* msg = new Message(0, 2, Message::PRIORITY_NORMAL);
|
| - msg->WriteInt64(base::TimeTicks::Now().ToInternalValue());
|
| - msg->WriteInt(msgid);
|
| - msg->WriteString(payload);
|
| - channel_->Send(msg);
|
| - return true;
|
| - }
|
| -
|
| - private:
|
| - Channel* channel_;
|
| - EventTimeTracker latency_tracker_;
|
| -};
|
| -
|
| -class PerformanceChannelListener : public Listener {
|
| - public:
|
| - explicit PerformanceChannelListener(const std::string& label)
|
| - : label_(label),
|
| - sender_(NULL),
|
| - msg_count_(0),
|
| - msg_size_(0),
|
| - count_down_(0),
|
| - latency_tracker_("Server messages") {
|
| - 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) {
|
| - DCHECK_EQ(0, count_down_);
|
| - msg_count_ = msg_count;
|
| - msg_size_ = msg_size;
|
| - count_down_ = msg_count_;
|
| - payload_ = std::string(msg_size_, 'a');
|
| - }
|
| -
|
| - bool OnMessageReceived(const Message& message) override {
|
| - CHECK(sender_);
|
| -
|
| - base::PickleIterator iter(message);
|
| - int64_t time_internal;
|
| - EXPECT_TRUE(iter.ReadInt64(&time_internal));
|
| - int msgid;
|
| - EXPECT_TRUE(iter.ReadInt(&msgid));
|
| - std::string reflected_payload;
|
| - EXPECT_TRUE(iter.ReadString(&reflected_payload));
|
| -
|
| - // Include message deserialization in latency.
|
| - base::TimeTicks now = base::TimeTicks::Now();
|
| -
|
| - if (reflected_payload == "hello") {
|
| - // Start timing on hello.
|
| - latency_tracker_.Reset();
|
| - 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()));
|
| - } else {
|
| - DCHECK_EQ(payload_.size(), reflected_payload.size());
|
| -
|
| - latency_tracker_.AddEvent(
|
| - base::TimeTicks::FromInternalValue(time_internal), now);
|
| -
|
| - CHECK(count_down_ > 0);
|
| - count_down_--;
|
| - if (count_down_ == 0) {
|
| - perf_logger_.reset(); // Stop the perf timer now.
|
| - latency_tracker_.ShowResults();
|
| - base::MessageLoop::current()->QuitWhenIdle();
|
| - return true;
|
| - }
|
| - }
|
| -
|
| - Message* msg = new Message(0, 2, Message::PRIORITY_NORMAL);
|
| - msg->WriteInt64(base::TimeTicks::Now().ToInternalValue());
|
| - msg->WriteInt(count_down_);
|
| - msg->WriteString(payload_);
|
| - sender_->Send(msg);
|
| - return true;
|
| - }
|
| -
|
| - private:
|
| - std::string label_;
|
| - Sender* sender_;
|
| - int msg_count_;
|
| - size_t msg_size_;
|
| -
|
| - int count_down_;
|
| - std::string payload_;
|
| - EventTimeTracker latency_tracker_;
|
| - std::unique_ptr<base::PerfTimeLogger> perf_logger_;
|
| -};
|
| -
|
| -IPCChannelPerfTestBase::IPCChannelPerfTestBase() = default;
|
| -IPCChannelPerfTestBase::~IPCChannelPerfTestBase() = default;
|
| -
|
| -std::vector<PingPongTestParams>
|
| -IPCChannelPerfTestBase::GetDefaultTestParams() {
|
| - // Test several sizes. We use 12^N for message size, and limit the message
|
| - // count to keep the test duration reasonable.
|
| -#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> 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;
|
| -}
|
| -
|
| -void IPCChannelPerfTestBase::RunTestChannelPingPong(
|
| - const std::vector<PingPongTestParams>& params) {
|
| - auto message_loop = base::MakeUnique<base::MessageLoopForIO>();
|
| - mojo::edk::test::ScopedIPCSupport ipc_support(message_loop->task_runner());
|
| - InitWithCustomMessageLoop("MojoPerfTestClient", std::move(message_loop));
|
| -
|
| - // Set up IPC channel and start client.
|
| - PerformanceChannelListener listener("Channel");
|
| - CreateChannel(&listener);
|
| - listener.Init(channel());
|
| - ASSERT_TRUE(ConnectChannel());
|
| -
|
| - LockThreadAffinity thread_locker(kSharedCore);
|
| - for (size_t i = 0; i < params.size(); i++) {
|
| - listener.SetTestParams(params[i].message_count(),
|
| - params[i].message_size());
|
| -
|
| - // This initial message will kick-start the ping-pong of messages.
|
| - Message* message =
|
| - new Message(0, 2, Message::PRIORITY_NORMAL);
|
| - message->WriteInt64(base::TimeTicks::Now().ToInternalValue());
|
| - message->WriteInt(-1);
|
| - message->WriteString("hello");
|
| - sender()->Send(message);
|
| -
|
| - // Run message loop.
|
| - base::RunLoop().Run();
|
| - }
|
| -
|
| - // Send quit message.
|
| - Message* message = new Message(0, 2, Message::PRIORITY_NORMAL);
|
| - message->WriteInt64(base::TimeTicks::Now().ToInternalValue());
|
| - message->WriteInt(-1);
|
| - message->WriteString("quit");
|
| - sender()->Send(message);
|
| -
|
| - EXPECT_TRUE(WaitForClientShutdown());
|
| - DestroyChannel();
|
| -}
|
| -
|
| -void IPCChannelPerfTestBase::RunTestChannelProxyPingPong(
|
| - const std::vector<PingPongTestParams>& params) {
|
| - io_thread_.reset(new base::TestIOThread(base::TestIOThread::kAutoStart));
|
| - {
|
| - auto message_loop = base::MakeUnique<base::MessageLoopForIO>();
|
| - mojo::edk::test::ScopedIPCSupport ipc_support(io_thread_->task_runner());
|
| - InitWithCustomMessageLoop("MojoPerfTestClient", std::move(message_loop));
|
| -
|
| - // Set up IPC channel and start client.
|
| - PerformanceChannelListener listener("ChannelProxy");
|
| - auto channel_proxy = IPC::ChannelProxy::Create(
|
| - TakeHandle().release(), IPC::Channel::MODE_SERVER, &listener,
|
| - io_thread_->task_runner());
|
| - listener.Init(channel_proxy.get());
|
| -
|
| - LockThreadAffinity thread_locker(kSharedCore);
|
| - for (size_t i = 0; i < params.size(); i++) {
|
| - listener.SetTestParams(params[i].message_count(),
|
| - params[i].message_size());
|
| -
|
| - // This initial message will kick-start the ping-pong of messages.
|
| - Message* message = new Message(0, 2, Message::PRIORITY_NORMAL);
|
| - message->WriteInt64(base::TimeTicks::Now().ToInternalValue());
|
| - message->WriteInt(-1);
|
| - message->WriteString("hello");
|
| - channel_proxy->Send(message);
|
| -
|
| - // Run message loop.
|
| - base::RunLoop().Run();
|
| - }
|
| -
|
| - // Send quit message.
|
| - Message* message = new Message(0, 2, Message::PRIORITY_NORMAL);
|
| - message->WriteInt64(base::TimeTicks::Now().ToInternalValue());
|
| - message->WriteInt(-1);
|
| - message->WriteString("quit");
|
| - channel_proxy->Send(message);
|
| -
|
| - EXPECT_TRUE(WaitForClientShutdown());
|
| - channel_proxy.reset();
|
| - }
|
| -
|
| - io_thread_.reset();
|
| -}
|
| -
|
| -
|
| -PingPongTestClient::PingPongTestClient()
|
| - : listener_(new ChannelReflectorListener()) {
|
| -}
|
| -
|
| -PingPongTestClient::~PingPongTestClient() {
|
| -}
|
| -
|
| -int PingPongTestClient::RunMain() {
|
| - LockThreadAffinity thread_locker(kSharedCore);
|
| - std::unique_ptr<Channel> channel = CreateChannel(listener_.get());
|
| - listener_->Init(channel.get());
|
| - CHECK(channel->Connect());
|
| -
|
| - base::RunLoop().Run();
|
| - return 0;
|
| -}
|
| -
|
| -scoped_refptr<base::TaskRunner> PingPongTestClient::task_runner() {
|
| - return main_message_loop_.task_runner();
|
| -}
|
| -
|
| -LockThreadAffinity::LockThreadAffinity(int cpu_number)
|
| - : affinity_set_ok_(false) {
|
| -#if defined(OS_WIN)
|
| - const DWORD_PTR thread_mask = static_cast<DWORD_PTR>(1) << cpu_number;
|
| - old_affinity_ = SetThreadAffinityMask(GetCurrentThread(), thread_mask);
|
| - affinity_set_ok_ = old_affinity_ != 0;
|
| -#elif defined(OS_LINUX)
|
| - cpu_set_t cpuset;
|
| - CPU_ZERO(&cpuset);
|
| - CPU_SET(cpu_number, &cpuset);
|
| - auto get_result = sched_getaffinity(0, sizeof(old_cpuset_), &old_cpuset_);
|
| - DCHECK_EQ(0, get_result);
|
| - auto set_result = sched_setaffinity(0, sizeof(cpuset), &cpuset);
|
| - // Check for get_result failure, even though it should always succeed.
|
| - affinity_set_ok_ = (set_result == 0) && (get_result == 0);
|
| -#endif
|
| - if (!affinity_set_ok_)
|
| - LOG(WARNING) << "Failed to set thread affinity to CPU " << cpu_number;
|
| -}
|
| -
|
| -LockThreadAffinity::~LockThreadAffinity() {
|
| - if (!affinity_set_ok_)
|
| - return;
|
| -#if defined(OS_WIN)
|
| - auto set_result = SetThreadAffinityMask(GetCurrentThread(), old_affinity_);
|
| - DCHECK_NE(0u, set_result);
|
| -#elif defined(OS_LINUX)
|
| - auto set_result = sched_setaffinity(0, sizeof(old_cpuset_), &old_cpuset_);
|
| - DCHECK_EQ(0, set_result);
|
| -#endif
|
| -}
|
| -
|
| -} // namespace test
|
| -} // namespace IPC
|
|
|