12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "build/build_config.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <algorithm>
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <string>
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/basictypes.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/scoped_ptr.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/pickle.h"
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
15d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/test/perf_time_logger.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/threading/thread.h"
17eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ipc/ipc_channel.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ipc/ipc_channel_proxy.h"
20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ipc/ipc_descriptors.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ipc/ipc_message_utils.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ipc/ipc_sender.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ipc/ipc_test_base.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This test times the roundtrip IPC message cycle.
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// TODO(brettw): Make this test run by default.
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class IPCChannelPerfTest : public IPCTestBase {
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This class simply collects stats about abstract "events" (each of which has a
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// start time and an end time).
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class EventTimeTracker {
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  explicit EventTimeTracker(const char* name)
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : name_(name),
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        count_(0) {
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void AddEvent(const base::TimeTicks& start, const base::TimeTicks& end) {
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(end >= start);
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    count_++;
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::TimeDelta duration = end - start;
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    total_duration_ += duration;
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    max_duration_ = std::max(max_duration_, duration);
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void ShowResults() const {
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VLOG(1) << name_ << " count: " << count_;
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VLOG(1) << name_ << " total duration: "
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            << total_duration_.InMillisecondsF() << " ms";
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VLOG(1) << name_ << " average duration: "
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            << (total_duration_.InMillisecondsF() / static_cast<double>(count_))
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            << " ms";
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VLOG(1) << name_ << " maximum duration: "
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            << max_duration_.InMillisecondsF() << " ms";
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void Reset() {
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    count_ = 0;
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    total_duration_ = base::TimeDelta();
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    max_duration_ = base::TimeDelta();
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string name_;
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  uint64 count_;
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::TimeDelta total_duration_;
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::TimeDelta max_duration_;
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(EventTimeTracker);
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This channel listener just replies to all messages with the exact same
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// message. It assumes each message has one string parameter. When the string
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// "quit" is sent, it will exit.
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class ChannelReflectorListener : public IPC::Listener {
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ChannelReflectorListener()
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : channel_(NULL),
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        latency_tracker_("Client messages") {
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VLOG(1) << "Client listener up";
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~ChannelReflectorListener() {
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VLOG(1) << "Client listener down";
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    latency_tracker_.ShowResults();
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void Init(IPC::Channel* channel) {
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(!channel_);
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    channel_ = channel;
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CHECK(channel_);
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PickleIterator iter(message);
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int64 time_internal;
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_TRUE(iter.ReadInt64(&time_internal));
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int msgid;
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_TRUE(iter.ReadInt(&msgid));
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string payload;
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_TRUE(iter.ReadString(&payload));
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Include message deserialization in latency.
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::TimeTicks now = base::TimeTicks::Now();
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (payload == "hello") {
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      latency_tracker_.Reset();
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else if (payload == "quit") {
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      latency_tracker_.ShowResults();
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::MessageLoop::current()->QuitWhenIdle();
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Don't track hello and quit messages.
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      latency_tracker_.AddEvent(
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::TimeTicks::FromInternalValue(time_internal), now);
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1250f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    IPC::Message* msg = new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL);
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    msg->WriteInt64(base::TimeTicks::Now().ToInternalValue());
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    msg->WriteInt(msgid);
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    msg->WriteString(payload);
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    channel_->Send(msg);
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  IPC::Channel* channel_;
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EventTimeTracker latency_tracker_;
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class PerformanceChannelListener : public IPC::Listener {
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PerformanceChannelListener()
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : channel_(NULL),
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        msg_count_(0),
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        msg_size_(0),
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        count_down_(0),
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        latency_tracker_("Server messages") {
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VLOG(1) << "Server listener up";
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~PerformanceChannelListener() {
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VLOG(1) << "Server listener down";
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void Init(IPC::Channel* channel) {
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(!channel_);
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    channel_ = channel;
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Call this before running the message loop.
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void SetTestParams(int msg_count, size_t msg_size) {
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK_EQ(0, count_down_);
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    msg_count_ = msg_count;
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    msg_size_ = msg_size;
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    count_down_ = msg_count_;
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    payload_ = std::string(msg_size_, 'a');
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CHECK(channel_);
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PickleIterator iter(message);
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int64 time_internal;
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_TRUE(iter.ReadInt64(&time_internal));
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int msgid;
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_TRUE(iter.ReadInt(&msgid));
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string reflected_payload;
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_TRUE(iter.ReadString(&reflected_payload));
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Include message deserialization in latency.
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::TimeTicks now = base::TimeTicks::Now();
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (reflected_payload == "hello") {
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Start timing on hello.
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      latency_tracker_.Reset();
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DCHECK(!perf_logger_.get());
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      std::string test_name = base::StringPrintf(
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          "IPC_Perf_%dx_%u", msg_count_, static_cast<unsigned>(msg_size_));
187d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      perf_logger_.reset(new base::PerfTimeLogger(test_name.c_str()));
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DCHECK_EQ(payload_.size(), reflected_payload.size());
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      latency_tracker_.AddEvent(
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::TimeTicks::FromInternalValue(time_internal), now);
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CHECK(count_down_ > 0);
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      count_down_--;
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (count_down_ == 0) {
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        perf_logger_.reset();  // Stop the perf timer now.
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        latency_tracker_.ShowResults();
199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        base::MessageLoop::current()->QuitWhenIdle();
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return true;
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2040f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    IPC::Message* msg = new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL);
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    msg->WriteInt64(base::TimeTicks::Now().ToInternalValue());
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    msg->WriteInt(count_down_);
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    msg->WriteString(payload_);
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    channel_->Send(msg);
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  IPC::Channel* channel_;
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int msg_count_;
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size_t msg_size_;
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int count_down_;
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string payload_;
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EventTimeTracker latency_tracker_;
220d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  scoped_ptr<base::PerfTimeLogger> perf_logger_;
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(IPCChannelPerfTest, Performance) {
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Init("PerformanceClient");
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Set up IPC channel and start client.
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PerformanceChannelListener listener;
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateChannel(&listener);
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  listener.Init(channel());
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(ConnectChannel());
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(StartClient());
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const size_t kMsgSizeBase = 12;
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kMsgSizeMaxExp = 5;
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int msg_count = 100000;
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size_t msg_size = kMsgSizeBase;
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int i = 1; i <= kMsgSizeMaxExp; i++) {
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    listener.SetTestParams(msg_count, msg_size);
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // This initial message will kick-start the ping-pong of messages.
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    IPC::Message* message =
2420f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL);
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    message->WriteInt64(base::TimeTicks::Now().ToInternalValue());
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    message->WriteInt(-1);
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    message->WriteString("hello");
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sender()->Send(message);
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Run message loop.
249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::MessageLoop::current()->Run();
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    msg_size *= kMsgSizeBase;
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Send quit message.
2550f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  IPC::Message* message = new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL);
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  message->WriteInt64(base::TimeTicks::Now().ToInternalValue());
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  message->WriteInt(-1);
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  message->WriteString("quit");
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  sender()->Send(message);
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(WaitForClientShutdown());
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DestroyChannel();
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This message loop bounces all messages back to the sender.
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)MULTIPROCESS_IPC_TEST_CLIENT_MAIN(PerformanceClient) {
267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::MessageLoopForIO main_message_loop;
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ChannelReflectorListener listener;
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  IPC::Channel channel(IPCTestBase::GetChannelName("PerformanceClient"),
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       IPC::Channel::MODE_CLIENT,
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       &listener);
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  listener.Init(&channel);
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK(channel.Connect());
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::MessageLoop::current()->Run();
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 0;
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
280