1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
12 #include "base/bind.h"
13 #include "base/location.h"
14 #include "base/logging.h"
15 #include "base/macros.h"
16 #include "base/pickle.h"
17 #include "base/strings/stringprintf.h"
18 #include "base/test/perf_time_logger.h"
19 #include "base/time/time.h"
20 #include "mojo/common/test/test_utils.h"
21 #include "mojo/embedder/scoped_platform_handle.h"
22 #include "mojo/system/channel.h"
23 #include "mojo/system/local_message_pipe_endpoint.h"
24 #include "mojo/system/message_pipe.h"
25 #include "mojo/system/message_pipe_test_utils.h"
26 #include "mojo/system/proxy_message_pipe_endpoint.h"
27 #include "mojo/system/raw_channel.h"
28 #include "mojo/system/test_utils.h"
29 #include "testing/gtest/include/gtest/gtest.h"
35 class MultiprocessMessagePipePerfTest
36 : public test::MultiprocessMessagePipeTestBase
{
38 MultiprocessMessagePipePerfTest() : message_count_(0), message_size_(0) {}
40 void SetUpMeasurement(int message_count
, size_t message_size
) {
41 message_count_
= message_count
;
42 message_size_
= message_size
;
44 payload_
.WriteString(std::string(message_size
, '*'));
45 read_buffer_
.resize(message_size
* 2);
49 void WriteWaitThenRead(scoped_refptr
<MessagePipe
> mp
) {
50 CHECK_EQ(mp
->WriteMessage(0,
51 UserPointer
<const void>(payload_
.data()),
52 static_cast<uint32_t>(payload_
.size()),
54 MOJO_WRITE_MESSAGE_FLAG_NONE
),
56 HandleSignalsState hss
;
57 CHECK_EQ(test::WaitIfNecessary(mp
, MOJO_HANDLE_SIGNAL_READABLE
, &hss
),
59 uint32_t read_buffer_size
= static_cast<uint32_t>(read_buffer_
.size());
60 CHECK_EQ(mp
->ReadMessage(0,
61 UserPointer
<void>(&read_buffer_
[0]),
62 MakeUserPointer(&read_buffer_size
),
65 MOJO_READ_MESSAGE_FLAG_NONE
),
67 CHECK_EQ(read_buffer_size
, static_cast<uint32_t>(payload_
.size()));
70 void SendQuitMessage(scoped_refptr
<MessagePipe
> mp
) {
71 CHECK_EQ(mp
->WriteMessage(0,
72 UserPointer
<const void>(""),
75 MOJO_WRITE_MESSAGE_FLAG_NONE
),
79 void Measure(scoped_refptr
<MessagePipe
> mp
) {
80 // Have one ping-pong to ensure channel being established.
81 WriteWaitThenRead(mp
);
83 std::string test_name
=
84 base::StringPrintf("IPC_Perf_%dx_%u",
86 static_cast<unsigned>(message_size_
));
87 base::PerfTimeLogger
logger(test_name
.c_str());
89 for (int i
= 0; i
< message_count_
; ++i
)
90 WriteWaitThenRead(mp
);
99 std::string read_buffer_
;
100 scoped_ptr
<base::PerfTimeLogger
> perf_logger_
;
103 // For each message received, sends a reply message with the same contents
104 // repeated twice, until the other end is closed or it receives "quitquitquit"
105 // (which it doesn't reply to). It'll return the number of messages received,
106 // not including any "quitquitquit" message, modulo 100.
107 MOJO_MULTIPROCESS_TEST_CHILD_MAIN(PingPongClient
) {
108 embedder::SimplePlatformSupport platform_support
;
109 test::ChannelThread
channel_thread(&platform_support
);
110 embedder::ScopedPlatformHandle client_platform_handle
=
111 mojo::test::MultiprocessTestHelper::client_platform_handle
.Pass();
112 CHECK(client_platform_handle
.is_valid());
113 scoped_refptr
<MessagePipe
> mp(new MessagePipe(
114 scoped_ptr
<MessagePipeEndpoint
>(new LocalMessagePipeEndpoint()),
115 scoped_ptr
<MessagePipeEndpoint
>(new ProxyMessagePipeEndpoint())));
116 channel_thread
.Start(client_platform_handle
.Pass(), mp
);
118 std::string
buffer(1000000, '\0');
121 // Wait for our end of the message pipe to be readable.
122 HandleSignalsState hss
;
124 test::WaitIfNecessary(mp
, MOJO_HANDLE_SIGNAL_READABLE
, &hss
);
125 if (result
!= MOJO_RESULT_OK
) {
130 uint32_t read_size
= static_cast<uint32_t>(buffer
.size());
131 CHECK_EQ(mp
->ReadMessage(0,
132 UserPointer
<void>(&buffer
[0]),
133 MakeUserPointer(&read_size
),
136 MOJO_READ_MESSAGE_FLAG_NONE
),
139 // Empty message indicates quitting
143 CHECK_EQ(mp
->WriteMessage(0,
144 UserPointer
<const void>(&buffer
[0]),
145 static_cast<uint32_t>(read_size
),
147 MOJO_WRITE_MESSAGE_FLAG_NONE
),
155 // Repeatedly sends messages as previous one got replied by the child.
156 // Waits for the child to close its end before quitting once specified
157 // number of messages has been sent.
158 TEST_F(MultiprocessMessagePipePerfTest
, PingPong
) {
159 helper()->StartChild("PingPongClient");
161 scoped_refptr
<MessagePipe
> mp(new MessagePipe(
162 scoped_ptr
<MessagePipeEndpoint
>(new LocalMessagePipeEndpoint()),
163 scoped_ptr
<MessagePipeEndpoint
>(new ProxyMessagePipeEndpoint())));
166 // This values are set to align with one at ipc_pertests.cc for comparison.
167 const size_t kMsgSize
[5] = {12, 144, 1728, 20736, 248832};
168 const int kMessageCount
[5] = {50000, 50000, 50000, 12000, 1000};
170 for (size_t i
= 0; i
< 5; i
++) {
171 SetUpMeasurement(kMessageCount
[i
], kMsgSize
[i
]);
177 EXPECT_EQ(0, helper()->WaitForChildShutdown());
181 } // namespace system