OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // This tests the performance of the C API. | 5 // This tests the performance of the C API. |
6 | 6 |
7 #include "mojo/public/c/system/core.h" | 7 #include "mojo/public/c/system/core.h" |
8 | 8 |
9 #include <assert.h> | 9 #include <assert.h> |
10 #include <stddef.h> | 10 #include <stddef.h> |
(...skipping 10 matching lines...) Expand all Loading... |
21 #include <time.h> | 21 #include <time.h> |
22 #include "mojo/public/cpp/utility/thread.h" | 22 #include "mojo/public/cpp/utility/thread.h" |
23 #endif // !defined(WIN32) | 23 #endif // !defined(WIN32) |
24 | 24 |
25 namespace { | 25 namespace { |
26 | 26 |
27 #if !defined(WIN32) | 27 #if !defined(WIN32) |
28 class MessagePipeWriterThread : public mojo::Thread { | 28 class MessagePipeWriterThread : public mojo::Thread { |
29 public: | 29 public: |
30 MessagePipeWriterThread(MojoHandle handle, uint32_t num_bytes) | 30 MessagePipeWriterThread(MojoHandle handle, uint32_t num_bytes) |
31 : handle_(handle), | 31 : handle_(handle), num_bytes_(num_bytes), num_writes_(0) {} |
32 num_bytes_(num_bytes), | |
33 num_writes_(0) {} | |
34 virtual ~MessagePipeWriterThread() {} | 32 virtual ~MessagePipeWriterThread() {} |
35 | 33 |
36 virtual void Run() MOJO_OVERRIDE { | 34 virtual void Run() MOJO_OVERRIDE { |
37 char buffer[10000]; | 35 char buffer[10000]; |
38 assert(num_bytes_ <= sizeof(buffer)); | 36 assert(num_bytes_ <= sizeof(buffer)); |
39 | 37 |
40 // TODO(vtl): Should I throttle somehow? | 38 // TODO(vtl): Should I throttle somehow? |
41 for (;;) { | 39 for (;;) { |
42 MojoResult result = MojoWriteMessage(handle_, buffer, num_bytes_, NULL, 0, | 40 MojoResult result = MojoWriteMessage( |
43 MOJO_WRITE_MESSAGE_FLAG_NONE); | 41 handle_, buffer, num_bytes_, NULL, 0, MOJO_WRITE_MESSAGE_FLAG_NONE); |
44 if (result == MOJO_RESULT_OK) { | 42 if (result == MOJO_RESULT_OK) { |
45 num_writes_++; | 43 num_writes_++; |
46 continue; | 44 continue; |
47 } | 45 } |
48 | 46 |
49 // We failed to write. | 47 // We failed to write. |
50 // Either |handle_| or its peer was closed. | 48 // Either |handle_| or its peer was closed. |
51 assert(result == MOJO_RESULT_INVALID_ARGUMENT || | 49 assert(result == MOJO_RESULT_INVALID_ARGUMENT || |
52 result == MOJO_RESULT_FAILED_PRECONDITION); | 50 result == MOJO_RESULT_FAILED_PRECONDITION); |
53 break; | 51 break; |
54 } | 52 } |
55 } | 53 } |
56 | 54 |
57 // Use only after joining the thread. | 55 // Use only after joining the thread. |
58 int64_t num_writes() const { return num_writes_; } | 56 int64_t num_writes() const { return num_writes_; } |
59 | 57 |
60 private: | 58 private: |
61 const MojoHandle handle_; | 59 const MojoHandle handle_; |
62 const uint32_t num_bytes_; | 60 const uint32_t num_bytes_; |
63 int64_t num_writes_; | 61 int64_t num_writes_; |
64 | 62 |
65 MOJO_DISALLOW_COPY_AND_ASSIGN(MessagePipeWriterThread); | 63 MOJO_DISALLOW_COPY_AND_ASSIGN(MessagePipeWriterThread); |
66 }; | 64 }; |
67 | 65 |
68 class MessagePipeReaderThread : public mojo::Thread { | 66 class MessagePipeReaderThread : public mojo::Thread { |
69 public: | 67 public: |
70 explicit MessagePipeReaderThread(MojoHandle handle) | 68 explicit MessagePipeReaderThread(MojoHandle handle) |
71 : handle_(handle), | 69 : handle_(handle), num_reads_(0) {} |
72 num_reads_(0) { | |
73 } | |
74 virtual ~MessagePipeReaderThread() {} | 70 virtual ~MessagePipeReaderThread() {} |
75 | 71 |
76 virtual void Run() MOJO_OVERRIDE { | 72 virtual void Run() MOJO_OVERRIDE { |
77 char buffer[10000]; | 73 char buffer[10000]; |
78 | 74 |
79 for (;;) { | 75 for (;;) { |
80 uint32_t num_bytes = static_cast<uint32_t>(sizeof(buffer)); | 76 uint32_t num_bytes = static_cast<uint32_t>(sizeof(buffer)); |
81 MojoResult result = MojoReadMessage(handle_, buffer, &num_bytes, NULL, | 77 MojoResult result = MojoReadMessage( |
82 NULL, MOJO_READ_MESSAGE_FLAG_NONE); | 78 handle_, buffer, &num_bytes, NULL, NULL, MOJO_READ_MESSAGE_FLAG_NONE); |
83 if (result == MOJO_RESULT_OK) { | 79 if (result == MOJO_RESULT_OK) { |
84 num_reads_++; | 80 num_reads_++; |
85 continue; | 81 continue; |
86 } | 82 } |
87 | 83 |
88 if (result == MOJO_RESULT_SHOULD_WAIT) { | 84 if (result == MOJO_RESULT_SHOULD_WAIT) { |
89 result = MojoWait(handle_, MOJO_HANDLE_SIGNAL_READABLE, | 85 result = MojoWait( |
90 MOJO_DEADLINE_INDEFINITE); | 86 handle_, MOJO_HANDLE_SIGNAL_READABLE, MOJO_DEADLINE_INDEFINITE); |
91 if (result == MOJO_RESULT_OK) { | 87 if (result == MOJO_RESULT_OK) { |
92 // Go to the top of the loop to read again. | 88 // Go to the top of the loop to read again. |
93 continue; | 89 continue; |
94 } | 90 } |
95 } | 91 } |
96 | 92 |
97 // We failed to read and possibly failed to wait. | 93 // We failed to read and possibly failed to wait. |
98 // Either |handle_| or its peer was closed. | 94 // Either |handle_| or its peer was closed. |
99 assert(result == MOJO_RESULT_INVALID_ARGUMENT || | 95 assert(result == MOJO_RESULT_INVALID_ARGUMENT || |
100 result == MOJO_RESULT_FAILED_PRECONDITION); | 96 result == MOJO_RESULT_FAILED_PRECONDITION); |
(...skipping 10 matching lines...) Expand all Loading... |
111 | 107 |
112 MOJO_DISALLOW_COPY_AND_ASSIGN(MessagePipeReaderThread); | 108 MOJO_DISALLOW_COPY_AND_ASSIGN(MessagePipeReaderThread); |
113 }; | 109 }; |
114 #endif // !defined(WIN32) | 110 #endif // !defined(WIN32) |
115 | 111 |
116 class CorePerftest : public testing::Test { | 112 class CorePerftest : public testing::Test { |
117 public: | 113 public: |
118 CorePerftest() : buffer_(NULL), num_bytes_(0) {} | 114 CorePerftest() : buffer_(NULL), num_bytes_(0) {} |
119 virtual ~CorePerftest() {} | 115 virtual ~CorePerftest() {} |
120 | 116 |
121 static void NoOp(void* /*closure*/) { | 117 static void NoOp(void* /*closure*/) {} |
122 } | |
123 | 118 |
124 static void MessagePipe_CreateAndClose(void* closure) { | 119 static void MessagePipe_CreateAndClose(void* closure) { |
125 CorePerftest* self = static_cast<CorePerftest*>(closure); | 120 CorePerftest* self = static_cast<CorePerftest*>(closure); |
126 MojoResult result MOJO_ALLOW_UNUSED; | 121 MojoResult result MOJO_ALLOW_UNUSED; |
127 result = MojoCreateMessagePipe(NULL, &self->h0_, &self->h1_); | 122 result = MojoCreateMessagePipe(NULL, &self->h0_, &self->h1_); |
128 assert(result == MOJO_RESULT_OK); | 123 assert(result == MOJO_RESULT_OK); |
129 result = MojoClose(self->h0_); | 124 result = MojoClose(self->h0_); |
130 assert(result == MOJO_RESULT_OK); | 125 assert(result == MOJO_RESULT_OK); |
131 result = MojoClose(self->h1_); | 126 result = MojoClose(self->h1_); |
132 assert(result == MOJO_RESULT_OK); | 127 assert(result == MOJO_RESULT_OK); |
133 } | 128 } |
134 | 129 |
135 static void MessagePipe_WriteAndRead(void* closure) { | 130 static void MessagePipe_WriteAndRead(void* closure) { |
136 CorePerftest* self = static_cast<CorePerftest*>(closure); | 131 CorePerftest* self = static_cast<CorePerftest*>(closure); |
137 MojoResult result MOJO_ALLOW_UNUSED; | 132 MojoResult result MOJO_ALLOW_UNUSED; |
138 result = MojoWriteMessage(self->h0_, | 133 result = MojoWriteMessage(self->h0_, |
139 self->buffer_, self->num_bytes_, | 134 self->buffer_, |
140 NULL, 0, | 135 self->num_bytes_, |
| 136 NULL, |
| 137 0, |
141 MOJO_WRITE_MESSAGE_FLAG_NONE); | 138 MOJO_WRITE_MESSAGE_FLAG_NONE); |
142 assert(result == MOJO_RESULT_OK); | 139 assert(result == MOJO_RESULT_OK); |
143 uint32_t read_bytes = self->num_bytes_; | 140 uint32_t read_bytes = self->num_bytes_; |
144 result = MojoReadMessage(self->h1_, | 141 result = MojoReadMessage(self->h1_, |
145 self->buffer_, &read_bytes, | 142 self->buffer_, |
146 NULL, NULL, | 143 &read_bytes, |
| 144 NULL, |
| 145 NULL, |
147 MOJO_READ_MESSAGE_FLAG_NONE); | 146 MOJO_READ_MESSAGE_FLAG_NONE); |
148 assert(result == MOJO_RESULT_OK); | 147 assert(result == MOJO_RESULT_OK); |
149 } | 148 } |
150 | 149 |
151 static void MessagePipe_EmptyRead(void* closure) { | 150 static void MessagePipe_EmptyRead(void* closure) { |
152 CorePerftest* self = static_cast<CorePerftest*>(closure); | 151 CorePerftest* self = static_cast<CorePerftest*>(closure); |
153 MojoResult result MOJO_ALLOW_UNUSED; | 152 MojoResult result MOJO_ALLOW_UNUSED; |
154 result = MojoReadMessage(self->h0_, | 153 result = MojoReadMessage( |
155 NULL, NULL, | 154 self->h0_, NULL, NULL, NULL, NULL, MOJO_READ_MESSAGE_FLAG_MAY_DISCARD); |
156 NULL, NULL, | |
157 MOJO_READ_MESSAGE_FLAG_MAY_DISCARD); | |
158 assert(result == MOJO_RESULT_SHOULD_WAIT); | 155 assert(result == MOJO_RESULT_SHOULD_WAIT); |
159 } | 156 } |
160 | 157 |
161 protected: | 158 protected: |
162 #if !defined(WIN32) | 159 #if !defined(WIN32) |
163 void DoMessagePipeThreadedTest(unsigned num_writers, | 160 void DoMessagePipeThreadedTest(unsigned num_writers, |
164 unsigned num_readers, | 161 unsigned num_readers, |
165 uint32_t num_bytes) { | 162 uint32_t num_bytes) { |
166 static const int64_t kPerftestTimeMicroseconds = 3 * 1000000; | 163 static const int64_t kPerftestTimeMicroseconds = 3 * 1000000; |
167 | 164 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
216 } | 213 } |
217 writers.clear(); | 214 writers.clear(); |
218 int64_t num_reads = 0; | 215 int64_t num_reads = 0; |
219 for (unsigned i = 0; i < num_readers; i++) { | 216 for (unsigned i = 0; i < num_readers; i++) { |
220 num_reads += readers[i]->num_reads(); | 217 num_reads += readers[i]->num_reads(); |
221 delete readers[i]; | 218 delete readers[i]; |
222 } | 219 } |
223 readers.clear(); | 220 readers.clear(); |
224 | 221 |
225 char test_name[200]; | 222 char test_name[200]; |
226 sprintf(test_name, "MessagePipe_Threaded_Writes_%uw_%ur_%ubytes", | 223 sprintf(test_name, |
227 num_writers, num_readers, static_cast<unsigned>(num_bytes)); | 224 "MessagePipe_Threaded_Writes_%uw_%ur_%ubytes", |
228 mojo::test::LogPerfResult(test_name, | 225 num_writers, |
229 1000000.0 * static_cast<double>(num_writes) / | 226 num_readers, |
230 (end_time - start_time), | 227 static_cast<unsigned>(num_bytes)); |
231 "writes/second"); | 228 mojo::test::LogPerfResult( |
232 sprintf(test_name, "MessagePipe_Threaded_Reads_%uw_%ur_%ubytes", | 229 test_name, |
233 num_writers, num_readers, static_cast<unsigned>(num_bytes)); | 230 1000000.0 * static_cast<double>(num_writes) / (end_time - start_time), |
234 mojo::test::LogPerfResult(test_name, | 231 "writes/second"); |
235 1000000.0 * static_cast<double>(num_reads) / | 232 sprintf(test_name, |
236 (end_time - start_time), | 233 "MessagePipe_Threaded_Reads_%uw_%ur_%ubytes", |
237 "reads/second"); | 234 num_writers, |
| 235 num_readers, |
| 236 static_cast<unsigned>(num_bytes)); |
| 237 mojo::test::LogPerfResult( |
| 238 test_name, |
| 239 1000000.0 * static_cast<double>(num_reads) / (end_time - start_time), |
| 240 "reads/second"); |
238 } | 241 } |
239 #endif // !defined(WIN32) | 242 #endif // !defined(WIN32) |
240 | 243 |
241 MojoHandle h0_; | 244 MojoHandle h0_; |
242 MojoHandle h1_; | 245 MojoHandle h1_; |
243 | 246 |
244 void* buffer_; | 247 void* buffer_; |
245 uint32_t num_bytes_; | 248 uint32_t num_bytes_; |
246 | 249 |
247 private: | 250 private: |
248 #if !defined(WIN32) | 251 #if !defined(WIN32) |
249 void Sleep(int64_t microseconds) { | 252 void Sleep(int64_t microseconds) { |
250 struct timespec req = { | 253 struct timespec req = { |
251 static_cast<time_t>(microseconds / 1000000), // Seconds. | 254 static_cast<time_t>(microseconds / 1000000), // Seconds. |
252 static_cast<long>(microseconds % 1000000) * 1000L // Nanoseconds. | 255 static_cast<long>(microseconds % 1000000) * 1000L // Nanoseconds. |
253 }; | 256 }; |
254 int rv MOJO_ALLOW_UNUSED; | 257 int rv MOJO_ALLOW_UNUSED; |
255 rv = nanosleep(&req, NULL); | 258 rv = nanosleep(&req, NULL); |
256 assert(rv == 0); | 259 assert(rv == 0); |
257 } | 260 } |
258 #endif // !defined(WIN32) | 261 #endif // !defined(WIN32) |
259 | 262 |
260 MOJO_DISALLOW_COPY_AND_ASSIGN(CorePerftest); | 263 MOJO_DISALLOW_COPY_AND_ASSIGN(CorePerftest); |
261 }; | 264 }; |
262 | 265 |
263 // A no-op test so we can compare performance. | 266 // A no-op test so we can compare performance. |
264 TEST_F(CorePerftest, NoOp) { | 267 TEST_F(CorePerftest, NoOp) { |
265 mojo::test::IterateAndReportPerf("NoOp", &CorePerftest::NoOp, this); | 268 mojo::test::IterateAndReportPerf("NoOp", &CorePerftest::NoOp, this); |
266 } | 269 } |
267 | 270 |
268 TEST_F(CorePerftest, MessagePipe_CreateAndClose) { | 271 TEST_F(CorePerftest, MessagePipe_CreateAndClose) { |
269 mojo::test::IterateAndReportPerf("MessagePipe_CreateAndClose", | 272 mojo::test::IterateAndReportPerf("MessagePipe_CreateAndClose", |
270 &CorePerftest::MessagePipe_CreateAndClose, | 273 &CorePerftest::MessagePipe_CreateAndClose, |
271 this); | 274 this); |
272 } | 275 } |
273 | 276 |
274 TEST_F(CorePerftest, MessagePipe_WriteAndRead) { | 277 TEST_F(CorePerftest, MessagePipe_WriteAndRead) { |
275 MojoResult result MOJO_ALLOW_UNUSED; | 278 MojoResult result MOJO_ALLOW_UNUSED; |
276 result = MojoCreateMessagePipe(NULL, &h0_, &h1_); | 279 result = MojoCreateMessagePipe(NULL, &h0_, &h1_); |
277 assert(result == MOJO_RESULT_OK); | 280 assert(result == MOJO_RESULT_OK); |
278 char buffer[10000] = { 0 }; | 281 char buffer[10000] = {0}; |
279 buffer_ = buffer; | 282 buffer_ = buffer; |
280 num_bytes_ = 10u; | 283 num_bytes_ = 10u; |
281 mojo::test::IterateAndReportPerf("MessagePipe_WriteAndRead_10bytes", | 284 mojo::test::IterateAndReportPerf("MessagePipe_WriteAndRead_10bytes", |
282 &CorePerftest::MessagePipe_WriteAndRead, | 285 &CorePerftest::MessagePipe_WriteAndRead, |
283 this); | 286 this); |
284 num_bytes_ = 100u; | 287 num_bytes_ = 100u; |
285 mojo::test::IterateAndReportPerf("MessagePipe_WriteAndRead_100bytes", | 288 mojo::test::IterateAndReportPerf("MessagePipe_WriteAndRead_100bytes", |
286 &CorePerftest::MessagePipe_WriteAndRead, | 289 &CorePerftest::MessagePipe_WriteAndRead, |
287 this); | 290 this); |
288 num_bytes_ = 1000u; | 291 num_bytes_ = 1000u; |
289 mojo::test::IterateAndReportPerf("MessagePipe_WriteAndRead_1000bytes", | 292 mojo::test::IterateAndReportPerf("MessagePipe_WriteAndRead_1000bytes", |
290 &CorePerftest::MessagePipe_WriteAndRead, | 293 &CorePerftest::MessagePipe_WriteAndRead, |
291 this); | 294 this); |
292 num_bytes_ = 10000u; | 295 num_bytes_ = 10000u; |
293 mojo::test::IterateAndReportPerf("MessagePipe_WriteAndRead_10000bytes", | 296 mojo::test::IterateAndReportPerf("MessagePipe_WriteAndRead_10000bytes", |
294 &CorePerftest::MessagePipe_WriteAndRead, | 297 &CorePerftest::MessagePipe_WriteAndRead, |
295 this); | 298 this); |
296 result = MojoClose(h0_); | 299 result = MojoClose(h0_); |
297 assert(result == MOJO_RESULT_OK); | 300 assert(result == MOJO_RESULT_OK); |
298 result = MojoClose(h1_); | 301 result = MojoClose(h1_); |
299 assert(result == MOJO_RESULT_OK); | 302 assert(result == MOJO_RESULT_OK); |
300 } | 303 } |
301 | 304 |
302 TEST_F(CorePerftest, MessagePipe_EmptyRead) { | 305 TEST_F(CorePerftest, MessagePipe_EmptyRead) { |
303 MojoResult result MOJO_ALLOW_UNUSED; | 306 MojoResult result MOJO_ALLOW_UNUSED; |
304 result = MojoCreateMessagePipe(NULL, &h0_, &h1_); | 307 result = MojoCreateMessagePipe(NULL, &h0_, &h1_); |
305 assert(result == MOJO_RESULT_OK); | 308 assert(result == MOJO_RESULT_OK); |
306 mojo::test::IterateAndReportPerf("MessagePipe_EmptyRead", | 309 mojo::test::IterateAndReportPerf( |
307 &CorePerftest::MessagePipe_EmptyRead, | 310 "MessagePipe_EmptyRead", &CorePerftest::MessagePipe_EmptyRead, this); |
308 this); | |
309 result = MojoClose(h0_); | 311 result = MojoClose(h0_); |
310 assert(result == MOJO_RESULT_OK); | 312 assert(result == MOJO_RESULT_OK); |
311 result = MojoClose(h1_); | 313 result = MojoClose(h1_); |
312 assert(result == MOJO_RESULT_OK); | 314 assert(result == MOJO_RESULT_OK); |
313 } | 315 } |
314 | 316 |
315 #if !defined(WIN32) | 317 #if !defined(WIN32) |
316 TEST_F(CorePerftest, MessagePipe_Threaded) { | 318 TEST_F(CorePerftest, MessagePipe_Threaded) { |
317 DoMessagePipeThreadedTest(1u, 1u, 100u); | 319 DoMessagePipeThreadedTest(1u, 1u, 100u); |
318 DoMessagePipeThreadedTest(2u, 2u, 100u); | 320 DoMessagePipeThreadedTest(2u, 2u, 100u); |
319 DoMessagePipeThreadedTest(3u, 3u, 100u); | 321 DoMessagePipeThreadedTest(3u, 3u, 100u); |
320 DoMessagePipeThreadedTest(10u, 10u, 100u); | 322 DoMessagePipeThreadedTest(10u, 10u, 100u); |
321 DoMessagePipeThreadedTest(10u, 1u, 100u); | 323 DoMessagePipeThreadedTest(10u, 1u, 100u); |
322 DoMessagePipeThreadedTest(1u, 10u, 100u); | 324 DoMessagePipeThreadedTest(1u, 10u, 100u); |
323 | 325 |
324 // For comparison of overhead: | 326 // For comparison of overhead: |
325 DoMessagePipeThreadedTest(1u, 1u, 10u); | 327 DoMessagePipeThreadedTest(1u, 1u, 10u); |
326 // 100 was done above. | 328 // 100 was done above. |
327 DoMessagePipeThreadedTest(1u, 1u, 1000u); | 329 DoMessagePipeThreadedTest(1u, 1u, 1000u); |
328 DoMessagePipeThreadedTest(1u, 1u, 10000u); | 330 DoMessagePipeThreadedTest(1u, 1u, 10000u); |
329 | 331 |
330 DoMessagePipeThreadedTest(3u, 3u, 10u); | 332 DoMessagePipeThreadedTest(3u, 3u, 10u); |
331 // 100 was done above. | 333 // 100 was done above. |
332 DoMessagePipeThreadedTest(3u, 3u, 1000u); | 334 DoMessagePipeThreadedTest(3u, 3u, 1000u); |
333 DoMessagePipeThreadedTest(3u, 3u, 10000u); | 335 DoMessagePipeThreadedTest(3u, 3u, 10000u); |
334 } | 336 } |
335 #endif // !defined(WIN32) | 337 #endif // !defined(WIN32) |
336 | 338 |
337 } // namespace | 339 } // namespace |
OLD | NEW |