Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(103)

Side by Side Diff: mojo/public/tests/system/core_perftest.cc

Issue 164693002: Mojo: Add a threaded perf test for (local) message pipes. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: doh Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « mojo/mojo_public.gypi ('k') | mojo/public/tests/test_support.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/system/core.h" 7 #include "mojo/public/system/core.h"
8 8
9 #include <assert.h> 9 #include <assert.h>
10 #include <stddef.h>
11 #include <stdint.h>
12 #include <stdio.h>
10 13
11 #include "mojo/public/system/macros.h" 14 #include "mojo/public/system/macros.h"
15 #include "mojo/public/tests/test_support.h"
12 #include "mojo/public/tests/test_utils.h" 16 #include "mojo/public/tests/test_utils.h"
13 #include "testing/gtest/include/gtest/gtest.h" 17 #include "testing/gtest/include/gtest/gtest.h"
14 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
15 namespace { 25 namespace {
16 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
17 class CorePerftest : public testing::Test { 116 class CorePerftest : public testing::Test {
18 public: 117 public:
19 CorePerftest() : buffer_(NULL), num_bytes_(0) {} 118 CorePerftest() : buffer_(NULL), num_bytes_(0) {}
20 virtual ~CorePerftest() {} 119 virtual ~CorePerftest() {}
21 120
22 static void NoOp(void* /*closure*/) { 121 static void NoOp(void* /*closure*/) {
23 } 122 }
24 123
25 static void MessagePipe_CreateAndClose(void* closure) { 124 static void MessagePipe_CreateAndClose(void* closure) {
26 CorePerftest* self = static_cast<CorePerftest*>(closure); 125 CorePerftest* self = static_cast<CorePerftest*>(closure);
(...skipping 26 matching lines...) Expand all
53 CorePerftest* self = static_cast<CorePerftest*>(closure); 152 CorePerftest* self = static_cast<CorePerftest*>(closure);
54 MojoResult result MOJO_ALLOW_UNUSED; 153 MojoResult result MOJO_ALLOW_UNUSED;
55 result = MojoReadMessage(self->h0_, 154 result = MojoReadMessage(self->h0_,
56 NULL, NULL, 155 NULL, NULL,
57 NULL, NULL, 156 NULL, NULL,
58 MOJO_READ_MESSAGE_FLAG_MAY_DISCARD); 157 MOJO_READ_MESSAGE_FLAG_MAY_DISCARD);
59 assert(result == MOJO_RESULT_SHOULD_WAIT); 158 assert(result == MOJO_RESULT_SHOULD_WAIT);
60 } 159 }
61 160
62 protected: 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
63 MojoHandle h0_; 241 MojoHandle h0_;
64 MojoHandle h1_; 242 MojoHandle h1_;
65 243
66 void* buffer_; 244 void* buffer_;
67 uint32_t num_bytes_; 245 uint32_t num_bytes_;
68 246
69 private: 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
70 MOJO_DISALLOW_COPY_AND_ASSIGN(CorePerftest); 260 MOJO_DISALLOW_COPY_AND_ASSIGN(CorePerftest);
71 }; 261 };
72 262
73 // A no-op test so we can compare performance. 263 // A no-op test so we can compare performance.
74 TEST_F(CorePerftest, NoOp) { 264 TEST_F(CorePerftest, NoOp) {
75 mojo::test::IterateAndReportPerf("NoOp", &CorePerftest::NoOp, this); 265 mojo::test::IterateAndReportPerf("NoOp", &CorePerftest::NoOp, this);
76 } 266 }
77 267
78 TEST_F(CorePerftest, MessagePipe_CreateAndClose) { 268 TEST_F(CorePerftest, MessagePipe_CreateAndClose) {
79 mojo::test::IterateAndReportPerf("MessagePipe_CreateAndClose", 269 mojo::test::IterateAndReportPerf("MessagePipe_CreateAndClose",
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
115 assert(result == MOJO_RESULT_OK); 305 assert(result == MOJO_RESULT_OK);
116 mojo::test::IterateAndReportPerf("MessagePipe_EmptyRead", 306 mojo::test::IterateAndReportPerf("MessagePipe_EmptyRead",
117 &CorePerftest::MessagePipe_EmptyRead, 307 &CorePerftest::MessagePipe_EmptyRead,
118 this); 308 this);
119 result = MojoClose(h0_); 309 result = MojoClose(h0_);
120 assert(result == MOJO_RESULT_OK); 310 assert(result == MOJO_RESULT_OK);
121 result = MojoClose(h1_); 311 result = MojoClose(h1_);
122 assert(result == MOJO_RESULT_OK); 312 assert(result == MOJO_RESULT_OK);
123 } 313 }
124 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
125 } // namespace 337 } // namespace
OLDNEW
« no previous file with comments | « mojo/mojo_public.gypi ('k') | mojo/public/tests/test_support.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698