Index: mojo/system/message_pipe_perftest.cc |
diff --git a/mojo/system/message_pipe_perftest.cc b/mojo/system/message_pipe_perftest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..4c1a1ab1975ea4c6495fd2c1f8870705c14e32c5 |
--- /dev/null |
+++ b/mojo/system/message_pipe_perftest.cc |
@@ -0,0 +1,182 @@ |
+// 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 <stdint.h> |
+#include <stdio.h> |
+#include <string.h> |
+ |
+#include <string> |
+#include <vector> |
+ |
+#include "base/bind.h" |
+#include "base/location.h" |
+#include "base/logging.h" |
+#include "base/macros.h" |
+#include "base/pickle.h" |
+#include "base/strings/stringprintf.h" |
+#include "base/test/perf_time_logger.h" |
+#include "base/time/time.h" |
+#include "mojo/common/test/test_utils.h" |
+#include "mojo/embedder/scoped_platform_handle.h" |
+#include "mojo/system/channel.h" |
+#include "mojo/system/local_message_pipe_endpoint.h" |
+#include "mojo/system/message_pipe.h" |
+#include "mojo/system/message_pipe_test_utils.h" |
+#include "mojo/system/proxy_message_pipe_endpoint.h" |
+#include "mojo/system/raw_channel.h" |
+#include "mojo/system/test_utils.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+namespace mojo { |
+namespace system { |
+namespace { |
+ |
+class MultiprocessMessagePipePerfTest |
+ : public test::MultiprocessMessagePipeTestBase { |
+ public: |
+ MultiprocessMessagePipePerfTest() : message_count_(0), message_size_(0) {} |
+ |
+ void SetUpMeasurement(int message_count, size_t message_size) { |
+ message_count_ = message_count; |
+ message_size_ = message_size; |
+ payload_ = Pickle(); |
+ payload_.WriteString(std::string(message_size, '*')); |
+ read_buffer_.resize(message_size * 2); |
+ } |
+ |
+ protected: |
+ void WriteWaitThenRead(scoped_refptr<MessagePipe> mp) { |
+ CHECK_EQ(mp->WriteMessage(0, |
+ UserPointer<const void>(payload_.data()), |
+ static_cast<uint32_t>(payload_.size()), |
+ NULL, |
+ MOJO_WRITE_MESSAGE_FLAG_NONE), |
+ MOJO_RESULT_OK); |
+ HandleSignalsState hss; |
+ CHECK_EQ(test::WaitIfNecessary(mp, MOJO_HANDLE_SIGNAL_READABLE, &hss), |
+ MOJO_RESULT_OK); |
+ uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer_.size()); |
+ CHECK_EQ(mp->ReadMessage(0, |
+ UserPointer<void>(&read_buffer_[0]), |
+ MakeUserPointer(&read_buffer_size), |
+ NULL, |
+ NULL, |
+ MOJO_READ_MESSAGE_FLAG_NONE), |
+ MOJO_RESULT_OK); |
+ CHECK_EQ(read_buffer_size, static_cast<uint32_t>(payload_.size())); |
+ } |
+ |
+ void SendQuitMessage(scoped_refptr<MessagePipe> mp) { |
+ CHECK_EQ(mp->WriteMessage(0, |
+ UserPointer<const void>(""), |
+ 0, |
+ NULL, |
+ MOJO_WRITE_MESSAGE_FLAG_NONE), |
+ MOJO_RESULT_OK); |
+ } |
+ |
+ void Measure(scoped_refptr<MessagePipe> mp) { |
+ // Have one ping-pong to ensure channel being established. |
+ WriteWaitThenRead(mp); |
+ |
+ std::string test_name = |
+ base::StringPrintf("IPC_Perf_%dx_%u", |
+ message_count_, |
+ static_cast<unsigned>(message_size_)); |
+ base::PerfTimeLogger logger(test_name.c_str()); |
+ |
+ for (int i = 0; i < message_count_; ++i) |
+ WriteWaitThenRead(mp); |
+ |
+ logger.Done(); |
+ } |
+ |
+ private: |
+ int message_count_; |
+ size_t message_size_; |
+ Pickle payload_; |
+ std::string read_buffer_; |
+ scoped_ptr<base::PerfTimeLogger> perf_logger_; |
+}; |
+ |
+// For each message received, sends a reply message with the same contents |
+// repeated twice, until the other end is closed or it receives "quitquitquit" |
+// (which it doesn't reply to). It'll return the number of messages received, |
+// not including any "quitquitquit" message, modulo 100. |
+MOJO_MULTIPROCESS_TEST_CHILD_MAIN(PingPongClient) { |
+ embedder::SimplePlatformSupport platform_support; |
+ test::ChannelThread channel_thread(&platform_support); |
+ embedder::ScopedPlatformHandle client_platform_handle = |
+ mojo::test::MultiprocessTestHelper::client_platform_handle.Pass(); |
+ CHECK(client_platform_handle.is_valid()); |
+ scoped_refptr<MessagePipe> mp(new MessagePipe( |
+ scoped_ptr<MessagePipeEndpoint>(new LocalMessagePipeEndpoint()), |
+ scoped_ptr<MessagePipeEndpoint>(new ProxyMessagePipeEndpoint()))); |
+ channel_thread.Start(client_platform_handle.Pass(), mp); |
+ |
+ std::string buffer(1000000, '\0'); |
+ int rv = 0; |
+ while (true) { |
+ // Wait for our end of the message pipe to be readable. |
+ HandleSignalsState hss; |
+ MojoResult result = |
+ test::WaitIfNecessary(mp, MOJO_HANDLE_SIGNAL_READABLE, &hss); |
+ if (result != MOJO_RESULT_OK) { |
+ rv = result; |
+ break; |
+ } |
+ |
+ uint32_t read_size = static_cast<uint32_t>(buffer.size()); |
+ CHECK_EQ(mp->ReadMessage(0, |
+ UserPointer<void>(&buffer[0]), |
+ MakeUserPointer(&read_size), |
+ NULL, |
+ NULL, |
+ MOJO_READ_MESSAGE_FLAG_NONE), |
+ MOJO_RESULT_OK); |
+ |
+ // Empty message indicates quitting |
+ if (0 == read_size) |
+ break; |
+ |
+ CHECK_EQ(mp->WriteMessage(0, |
+ UserPointer<const void>(&buffer[0]), |
+ static_cast<uint32_t>(read_size), |
+ NULL, |
+ MOJO_WRITE_MESSAGE_FLAG_NONE), |
+ MOJO_RESULT_OK); |
+ } |
+ |
+ mp->Close(0); |
+ return rv; |
+} |
+ |
+// Repeatedly sends messages as previous one got replied by the child. |
+// Waits for the child to close its end before quitting once specified |
+// number of messages has been sent. |
+TEST_F(MultiprocessMessagePipePerfTest, PingPong) { |
+ helper()->StartChild("PingPongClient"); |
+ |
+ scoped_refptr<MessagePipe> mp(new MessagePipe( |
+ scoped_ptr<MessagePipeEndpoint>(new LocalMessagePipeEndpoint()), |
+ scoped_ptr<MessagePipeEndpoint>(new ProxyMessagePipeEndpoint()))); |
+ Init(mp); |
+ |
+ // This values are set to align with one at ipc_pertests.cc for comparison. |
+ 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++) { |
+ SetUpMeasurement(kMessageCount[i], kMsgSize[i]); |
+ Measure(mp); |
+ } |
+ |
+ SendQuitMessage(mp); |
+ mp->Close(0); |
+ EXPECT_EQ(0, helper()->WaitForChildShutdown()); |
+} |
+ |
+} // namespace |
+} // namespace system |
+} // namespace mojo |