Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / mojo / public / tests / system / core_perftest.cc
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
3 // found in the LICENSE file.
4
5 // This tests the performance of the C API.
6
7 #include "mojo/public/system/core.h"
8
9 #include <assert.h>
10 #include <stddef.h>
11 #include <stdint.h>
12 #include <stdio.h>
13
14 #include "mojo/public/system/macros.h"
15 #include "mojo/public/tests/test_support.h"
16 #include "mojo/public/tests/test_utils.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18
19 // TODO(vtl): (here and below) crbug.com/342893
20 #if !defined(WIN32)
21 #include <time.h>
22 #include "mojo/public/utility/thread.h"
23 #endif  // !defined(WIN32)
24
25 namespace {
26
27 #if !defined(WIN32)
28 class MessagePipeWriterThread : public mojo::Thread {
29  public:
30   MessagePipeWriterThread(MojoHandle handle, uint32_t num_bytes)
31       : handle_(handle),
32         num_bytes_(num_bytes),
33         num_writes_(0) {}
34   virtual ~MessagePipeWriterThread() {}
35
36   virtual void Run() MOJO_OVERRIDE {
37     char buffer[10000];
38     assert(num_bytes_ <= sizeof(buffer));
39
40     // TODO(vtl): Should I throttle somehow?
41     for (;;) {
42       MojoResult result = MojoWriteMessage(handle_, buffer, num_bytes_, NULL, 0,
43                                            MOJO_WRITE_MESSAGE_FLAG_NONE);
44       if (result == MOJO_RESULT_OK) {
45         num_writes_++;
46         continue;
47       }
48
49       // We failed to write.
50       // Either |handle_| or its peer was closed.
51       assert(result == MOJO_RESULT_INVALID_ARGUMENT ||
52              result == MOJO_RESULT_FAILED_PRECONDITION);
53       break;
54     }
55   }
56
57   // Use only after joining the thread.
58   int64_t num_writes() const { return num_writes_; }
59
60  private:
61   const MojoHandle handle_;
62   const uint32_t num_bytes_;
63   int64_t num_writes_;
64
65   MOJO_DISALLOW_COPY_AND_ASSIGN(MessagePipeWriterThread);
66 };
67
68 class MessagePipeReaderThread : public mojo::Thread {
69  public:
70   explicit MessagePipeReaderThread(MojoHandle handle)
71       : handle_(handle),
72         num_reads_(0) {
73   }
74   virtual ~MessagePipeReaderThread() {}
75
76   virtual void Run() MOJO_OVERRIDE {
77     char buffer[10000];
78
79     for (;;) {
80       uint32_t num_bytes = static_cast<uint32_t>(sizeof(buffer));
81       MojoResult result = MojoReadMessage(handle_, buffer, &num_bytes, NULL,
82                                           NULL, MOJO_READ_MESSAGE_FLAG_NONE);
83       if (result == MOJO_RESULT_OK) {
84         num_reads_++;
85         continue;
86       }
87
88       if (result == MOJO_RESULT_SHOULD_WAIT) {
89         result = MojoWait(handle_, MOJO_WAIT_FLAG_READABLE,
90                           MOJO_DEADLINE_INDEFINITE);
91         if (result == MOJO_RESULT_OK) {
92           // Go to the top of the loop to read again.
93           continue;
94         }
95       }
96
97       // We failed to read and possibly failed to wait.
98       // Either |handle_| or its peer was closed.
99       assert(result == MOJO_RESULT_INVALID_ARGUMENT ||
100              result == MOJO_RESULT_FAILED_PRECONDITION);
101       break;
102     }
103   }
104
105   // Use only after joining the thread.
106   int64_t num_reads() const { return num_reads_; }
107
108  private:
109   const MojoHandle handle_;
110   int64_t num_reads_;
111
112   MOJO_DISALLOW_COPY_AND_ASSIGN(MessagePipeReaderThread);
113 };
114 #endif  // !defined(WIN32)
115
116 class CorePerftest : public testing::Test {
117  public:
118   CorePerftest() : buffer_(NULL), num_bytes_(0) {}
119   virtual ~CorePerftest() {}
120
121   static void NoOp(void* /*closure*/) {
122   }
123
124   static void MessagePipe_CreateAndClose(void* closure) {
125     CorePerftest* self = static_cast<CorePerftest*>(closure);
126     MojoResult result MOJO_ALLOW_UNUSED;
127     result = MojoCreateMessagePipe(&self->h0_, &self->h1_);
128     assert(result == MOJO_RESULT_OK);
129     result = MojoClose(self->h0_);
130     assert(result == MOJO_RESULT_OK);
131     result = MojoClose(self->h1_);
132     assert(result == MOJO_RESULT_OK);
133   }
134
135   static void MessagePipe_WriteAndRead(void* closure) {
136     CorePerftest* self = static_cast<CorePerftest*>(closure);
137     MojoResult result MOJO_ALLOW_UNUSED;
138     result = MojoWriteMessage(self->h0_,
139                               self->buffer_, self->num_bytes_,
140                               NULL, 0,
141                               MOJO_WRITE_MESSAGE_FLAG_NONE);
142     assert(result == MOJO_RESULT_OK);
143     uint32_t read_bytes = self->num_bytes_;
144     result = MojoReadMessage(self->h1_,
145                              self->buffer_, &read_bytes,
146                              NULL, NULL,
147                              MOJO_READ_MESSAGE_FLAG_NONE);
148     assert(result == MOJO_RESULT_OK);
149   }
150
151   static void MessagePipe_EmptyRead(void* closure) {
152     CorePerftest* self = static_cast<CorePerftest*>(closure);
153     MojoResult result MOJO_ALLOW_UNUSED;
154     result = MojoReadMessage(self->h0_,
155                              NULL, NULL,
156                              NULL, NULL,
157                              MOJO_READ_MESSAGE_FLAG_MAY_DISCARD);
158     assert(result == MOJO_RESULT_SHOULD_WAIT);
159   }
160
161  protected:
162 #if !defined(WIN32)
163   void DoMessagePipeThreadedTest(unsigned num_writers,
164                                  unsigned num_readers,
165                                  uint32_t num_bytes) {
166     static const int64_t kPerftestTimeMicroseconds = 3 * 1000000;
167
168     assert(num_writers > 0);
169     assert(num_readers > 0);
170
171     MojoResult result MOJO_ALLOW_UNUSED;
172     result = MojoCreateMessagePipe(&h0_, &h1_);
173     assert(result == MOJO_RESULT_OK);
174
175     std::vector<MessagePipeWriterThread*> writers;
176     for (unsigned i = 0; i < num_writers; i++)
177       writers.push_back(new MessagePipeWriterThread(h0_, num_bytes));
178
179     std::vector<MessagePipeReaderThread*> readers;
180     for (unsigned i = 0; i < num_readers; i++)
181       readers.push_back(new MessagePipeReaderThread(h1_));
182
183     // Start time here, just before we fire off the threads.
184     const MojoTimeTicks start_time = MojoGetTimeTicksNow();
185
186     // Interleave the starts.
187     for (unsigned i = 0; i < num_writers || i < num_readers; i++) {
188       if (i < num_writers)
189         writers[i]->Start();
190       if (i < num_readers)
191         readers[i]->Start();
192     }
193
194     Sleep(kPerftestTimeMicroseconds);
195
196     // Close both handles to make writers and readers stop immediately.
197     result = MojoClose(h0_);
198     assert(result == MOJO_RESULT_OK);
199     result = MojoClose(h1_);
200     assert(result == MOJO_RESULT_OK);
201
202     // Join everything.
203     for (unsigned i = 0; i < num_writers; i++)
204       writers[i]->Join();
205     for (unsigned i = 0; i < num_readers; i++)
206       readers[i]->Join();
207
208     // Stop time here.
209     MojoTimeTicks end_time = MojoGetTimeTicksNow();
210
211     // Add up write and read counts, and destroy the threads.
212     int64_t num_writes = 0;
213     for (unsigned i = 0; i < num_writers; i++) {
214       num_writes += writers[i]->num_writes();
215       delete writers[i];
216     }
217     writers.clear();
218     int64_t num_reads = 0;
219     for (unsigned i = 0; i < num_readers; i++) {
220       num_reads += readers[i]->num_reads();
221       delete readers[i];
222     }
223     readers.clear();
224
225     char test_name[200];
226     sprintf(test_name, "MessagePipe_Threaded_Writes_%uw_%ur_%ubytes",
227             num_writers, num_readers, static_cast<unsigned>(num_bytes));
228     mojo::test::LogPerfResult(test_name,
229                               1000000.0 * static_cast<double>(num_writes) /
230                                   (end_time - start_time),
231                               "writes/second");
232     sprintf(test_name, "MessagePipe_Threaded_Reads_%uw_%ur_%ubytes",
233             num_writers, num_readers, static_cast<unsigned>(num_bytes));
234     mojo::test::LogPerfResult(test_name,
235                               1000000.0 * static_cast<double>(num_reads) /
236                                   (end_time - start_time),
237                                   "reads/second");
238   }
239 #endif  // !defined(WIN32)
240
241   MojoHandle h0_;
242   MojoHandle h1_;
243
244   void* buffer_;
245   uint32_t num_bytes_;
246
247  private:
248 #if !defined(WIN32)
249   void Sleep(int64_t microseconds) {
250     struct timespec req = {
251       static_cast<time_t>(microseconds / 1000000),  // Seconds.
252       static_cast<long>(microseconds % 1000000) * 1000L  // Nanoseconds.
253     };
254     int rv MOJO_ALLOW_UNUSED;
255     rv = nanosleep(&req, NULL);
256     assert(rv == 0);
257   }
258 #endif  // !defined(WIN32)
259
260   MOJO_DISALLOW_COPY_AND_ASSIGN(CorePerftest);
261 };
262
263 // A no-op test so we can compare performance.
264 TEST_F(CorePerftest, NoOp) {
265   mojo::test::IterateAndReportPerf("NoOp", &CorePerftest::NoOp, this);
266 }
267
268 TEST_F(CorePerftest, MessagePipe_CreateAndClose) {
269   mojo::test::IterateAndReportPerf("MessagePipe_CreateAndClose",
270                                    &CorePerftest::MessagePipe_CreateAndClose,
271                                    this);
272 }
273
274 TEST_F(CorePerftest, MessagePipe_WriteAndRead) {
275   MojoResult result MOJO_ALLOW_UNUSED;
276   result = MojoCreateMessagePipe(&h0_, &h1_);
277   assert(result == MOJO_RESULT_OK);
278   char buffer[10000] = { 0 };
279   buffer_ = buffer;
280   num_bytes_ = 10u;
281   mojo::test::IterateAndReportPerf("MessagePipe_WriteAndRead_10bytes",
282                                    &CorePerftest::MessagePipe_WriteAndRead,
283                                    this);
284   num_bytes_ = 100u;
285   mojo::test::IterateAndReportPerf("MessagePipe_WriteAndRead_100bytes",
286                                    &CorePerftest::MessagePipe_WriteAndRead,
287                                    this);
288   num_bytes_ = 1000u;
289   mojo::test::IterateAndReportPerf("MessagePipe_WriteAndRead_1000bytes",
290                                    &CorePerftest::MessagePipe_WriteAndRead,
291                                    this);
292   num_bytes_ = 10000u;
293   mojo::test::IterateAndReportPerf("MessagePipe_WriteAndRead_10000bytes",
294                                    &CorePerftest::MessagePipe_WriteAndRead,
295                                    this);
296   result = MojoClose(h0_);
297   assert(result == MOJO_RESULT_OK);
298   result = MojoClose(h1_);
299   assert(result == MOJO_RESULT_OK);
300 }
301
302 TEST_F(CorePerftest, MessagePipe_EmptyRead) {
303   MojoResult result MOJO_ALLOW_UNUSED;
304   result = MojoCreateMessagePipe(&h0_, &h1_);
305   assert(result == MOJO_RESULT_OK);
306   mojo::test::IterateAndReportPerf("MessagePipe_EmptyRead",
307                                    &CorePerftest::MessagePipe_EmptyRead,
308                                    this);
309   result = MojoClose(h0_);
310   assert(result == MOJO_RESULT_OK);
311   result = MojoClose(h1_);
312   assert(result == MOJO_RESULT_OK);
313 }
314
315 #if !defined(WIN32)
316 TEST_F(CorePerftest, MessagePipe_Threaded) {
317   DoMessagePipeThreadedTest(1u, 1u, 100u);
318   DoMessagePipeThreadedTest(2u, 2u, 100u);
319   DoMessagePipeThreadedTest(3u, 3u, 100u);
320   DoMessagePipeThreadedTest(10u, 10u, 100u);
321   DoMessagePipeThreadedTest(10u, 1u, 100u);
322   DoMessagePipeThreadedTest(1u, 10u, 100u);
323
324   // For comparison of overhead:
325   DoMessagePipeThreadedTest(1u, 1u, 10u);
326   // 100 was done above.
327   DoMessagePipeThreadedTest(1u, 1u, 1000u);
328   DoMessagePipeThreadedTest(1u, 1u, 10000u);
329
330   DoMessagePipeThreadedTest(3u, 3u, 10u);
331   // 100 was done above.
332   DoMessagePipeThreadedTest(3u, 3u, 1000u);
333   DoMessagePipeThreadedTest(3u, 3u, 10000u);
334 }
335 #endif  // !defined(WIN32)
336
337 }  // namespace