This source file includes following definitions.
- count_
- AddEvent
- ShowResults
- Reset
- latency_tracker_
- Init
- OnMessageReceived
- latency_tracker_
- Init
- SetTestParams
- OnMessageReceived
- TEST_F
- MULTIPROCESS_IPC_TEST_CLIENT_MAIN
#include "build/build_config.h"
#include <algorithm>
#include <string>
#include "base/basictypes.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/pickle.h"
#include "base/strings/stringprintf.h"
#include "base/test/perf_time_logger.h"
#include "base/threading/thread.h"
#include "base/time/time.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 "ipc/ipc_test_base.h"
namespace {
class IPCChannelPerfTest : public IPCTestBase {
};
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 count_;
base::TimeDelta total_duration_;
base::TimeDelta max_duration_;
DISALLOW_COPY_AND_ASSIGN(EventTimeTracker);
};
class ChannelReflectorListener : public IPC::Listener {
public:
ChannelReflectorListener()
: channel_(NULL),
latency_tracker_("Client messages") {
VLOG(1) << "Client listener up";
}
virtual ~ChannelReflectorListener() {
VLOG(1) << "Client listener down";
latency_tracker_.ShowResults();
}
void Init(IPC::Channel* channel) {
DCHECK(!channel_);
channel_ = channel;
}
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
CHECK(channel_);
PickleIterator iter(message);
int64 time_internal;
EXPECT_TRUE(iter.ReadInt64(&time_internal));
int msgid;
EXPECT_TRUE(iter.ReadInt(&msgid));
std::string payload;
EXPECT_TRUE(iter.ReadString(&payload));
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 {
latency_tracker_.AddEvent(
base::TimeTicks::FromInternalValue(time_internal), now);
}
IPC::Message* msg = new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL);
msg->WriteInt64(base::TimeTicks::Now().ToInternalValue());
msg->WriteInt(msgid);
msg->WriteString(payload);
channel_->Send(msg);
return true;
}
private:
IPC::Channel* channel_;
EventTimeTracker latency_tracker_;
};
class PerformanceChannelListener : public IPC::Listener {
public:
PerformanceChannelListener()
: channel_(NULL),
msg_count_(0),
msg_size_(0),
count_down_(0),
latency_tracker_("Server messages") {
VLOG(1) << "Server listener up";
}
virtual ~PerformanceChannelListener() {
VLOG(1) << "Server listener down";
}
void Init(IPC::Channel* channel) {
DCHECK(!channel_);
channel_ = channel;
}
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');
}
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
CHECK(channel_);
PickleIterator iter(message);
int64 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));
base::TimeTicks now = base::TimeTicks::Now();
if (reflected_payload == "hello") {
latency_tracker_.Reset();
DCHECK(!perf_logger_.get());
std::string test_name = base::StringPrintf(
"IPC_Perf_%dx_%u", 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();
latency_tracker_.ShowResults();
base::MessageLoop::current()->QuitWhenIdle();
return true;
}
}
IPC::Message* msg = new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL);
msg->WriteInt64(base::TimeTicks::Now().ToInternalValue());
msg->WriteInt(count_down_);
msg->WriteString(payload_);
channel_->Send(msg);
return true;
}
private:
IPC::Channel* channel_;
int msg_count_;
size_t msg_size_;
int count_down_;
std::string payload_;
EventTimeTracker latency_tracker_;
scoped_ptr<base::PerfTimeLogger> perf_logger_;
};
TEST_F(IPCChannelPerfTest, Performance) {
Init("PerformanceClient");
PerformanceChannelListener listener;
CreateChannel(&listener);
listener.Init(channel());
ASSERT_TRUE(ConnectChannel());
ASSERT_TRUE(StartClient());
const size_t kMsgSize[5] = {12, 144, 1728, 20736, 248832};
const int kMessageCount[5] = {50000, 50000, 50000, 12000, 1000};
for (size_t i = 0; i < 5; i++) {
listener.SetTestParams(kMessageCount[i], kMsgSize[i]);
IPC::Message* message =
new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL);
message->WriteInt64(base::TimeTicks::Now().ToInternalValue());
message->WriteInt(-1);
message->WriteString("hello");
sender()->Send(message);
base::MessageLoop::current()->Run();
}
IPC::Message* message = new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL);
message->WriteInt64(base::TimeTicks::Now().ToInternalValue());
message->WriteInt(-1);
message->WriteString("quit");
sender()->Send(message);
EXPECT_TRUE(WaitForClientShutdown());
DestroyChannel();
}
MULTIPROCESS_IPC_TEST_CLIENT_MAIN(PerformanceClient) {
base::MessageLoopForIO main_message_loop;
ChannelReflectorListener listener;
IPC::Channel channel(IPCTestBase::GetChannelName("PerformanceClient"),
IPC::Channel::MODE_CLIENT,
&listener);
listener.Init(&channel);
CHECK(channel.Connect());
base::MessageLoop::current()->Run();
return 0;
}
}