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