summaryrefslogtreecommitdiffstats
path: root/mojo/public/tests/system/core_perftest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'mojo/public/tests/system/core_perftest.cc')
-rw-r--r--mojo/public/tests/system/core_perftest.cc212
1 files changed, 212 insertions, 0 deletions
diff --git a/mojo/public/tests/system/core_perftest.cc b/mojo/public/tests/system/core_perftest.cc
index bfb8ff3..6874375 100644
--- a/mojo/public/tests/system/core_perftest.cc
+++ b/mojo/public/tests/system/core_perftest.cc
@@ -7,13 +7,112 @@
#include "mojo/public/system/core.h"
#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
#include "mojo/public/system/macros.h"
+#include "mojo/public/tests/test_support.h"
#include "mojo/public/tests/test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
+// TODO(vtl): (here and below) crbug.com/342893
+#if !defined(WIN32)
+#include <time.h>
+#include "mojo/public/utility/thread.h"
+#endif // !defined(WIN32)
+
namespace {
+#if !defined(WIN32)
+class MessagePipeWriterThread : public mojo::Thread {
+ public:
+ MessagePipeWriterThread(MojoHandle handle, uint32_t num_bytes)
+ : handle_(handle),
+ num_bytes_(num_bytes),
+ num_writes_(0) {}
+ virtual ~MessagePipeWriterThread() {}
+
+ virtual void Run() MOJO_OVERRIDE {
+ char buffer[10000];
+ assert(num_bytes_ <= sizeof(buffer));
+
+ // TODO(vtl): Should I throttle somehow?
+ for (;;) {
+ MojoResult result = MojoWriteMessage(handle_, buffer, num_bytes_, NULL, 0,
+ MOJO_WRITE_MESSAGE_FLAG_NONE);
+ if (result == MOJO_RESULT_OK) {
+ num_writes_++;
+ continue;
+ }
+
+ // We failed to write.
+ // Either |handle_| or its peer was closed.
+ assert(result == MOJO_RESULT_INVALID_ARGUMENT ||
+ result == MOJO_RESULT_FAILED_PRECONDITION);
+ break;
+ }
+ }
+
+ // Use only after joining the thread.
+ int64_t num_writes() const { return num_writes_; }
+
+ private:
+ const MojoHandle handle_;
+ const uint32_t num_bytes_;
+ int64_t num_writes_;
+
+ MOJO_DISALLOW_COPY_AND_ASSIGN(MessagePipeWriterThread);
+};
+
+class MessagePipeReaderThread : public mojo::Thread {
+ public:
+ explicit MessagePipeReaderThread(MojoHandle handle)
+ : handle_(handle),
+ num_reads_(0) {
+ }
+ virtual ~MessagePipeReaderThread() {}
+
+ virtual void Run() MOJO_OVERRIDE {
+ char buffer[10000];
+
+ for (;;) {
+ uint32_t num_bytes = static_cast<uint32_t>(sizeof(buffer));
+ MojoResult result = MojoReadMessage(handle_, buffer, &num_bytes, NULL,
+ NULL, MOJO_READ_MESSAGE_FLAG_NONE);
+ if (result == MOJO_RESULT_OK) {
+ num_reads_++;
+ continue;
+ }
+
+ if (result == MOJO_RESULT_SHOULD_WAIT) {
+ result = MojoWait(handle_, MOJO_WAIT_FLAG_READABLE,
+ MOJO_DEADLINE_INDEFINITE);
+ if (result == MOJO_RESULT_OK) {
+ // Go to the top of the loop to read again.
+ continue;
+ }
+ }
+
+ // We failed to read and possibly failed to wait.
+ // Either |handle_| or its peer was closed.
+ assert(result == MOJO_RESULT_INVALID_ARGUMENT ||
+ result == MOJO_RESULT_FAILED_PRECONDITION);
+ break;
+ }
+ }
+
+ // Use only after joining the thread.
+ int64_t num_reads() const { return num_reads_; }
+
+ private:
+ const MojoHandle handle_;
+ int64_t num_reads_;
+
+ MOJO_DISALLOW_COPY_AND_ASSIGN(MessagePipeReaderThread);
+};
+#endif // !defined(WIN32)
+
class CorePerftest : public testing::Test {
public:
CorePerftest() : buffer_(NULL), num_bytes_(0) {}
@@ -60,6 +159,85 @@ class CorePerftest : public testing::Test {
}
protected:
+#if !defined(WIN32)
+ void DoMessagePipeThreadedTest(unsigned num_writers,
+ unsigned num_readers,
+ uint32_t num_bytes) {
+ static const int64_t kPerftestTimeMicroseconds = 3 * 1000000;
+
+ assert(num_writers > 0);
+ assert(num_readers > 0);
+
+ MojoResult result MOJO_ALLOW_UNUSED;
+ result = MojoCreateMessagePipe(&h0_, &h1_);
+ assert(result == MOJO_RESULT_OK);
+
+ std::vector<MessagePipeWriterThread*> writers;
+ for (unsigned i = 0; i < num_writers; i++)
+ writers.push_back(new MessagePipeWriterThread(h0_, num_bytes));
+
+ std::vector<MessagePipeReaderThread*> readers;
+ for (unsigned i = 0; i < num_readers; i++)
+ readers.push_back(new MessagePipeReaderThread(h1_));
+
+ // Start time here, just before we fire off the threads.
+ const MojoTimeTicks start_time = MojoGetTimeTicksNow();
+
+ // Interleave the starts.
+ for (unsigned i = 0; i < num_writers || i < num_readers; i++) {
+ if (i < num_writers)
+ writers[i]->Start();
+ if (i < num_readers)
+ readers[i]->Start();
+ }
+
+ Sleep(kPerftestTimeMicroseconds);
+
+ // Close both handles to make writers and readers stop immediately.
+ result = MojoClose(h0_);
+ assert(result == MOJO_RESULT_OK);
+ result = MojoClose(h1_);
+ assert(result == MOJO_RESULT_OK);
+
+ // Join everything.
+ for (unsigned i = 0; i < num_writers; i++)
+ writers[i]->Join();
+ for (unsigned i = 0; i < num_readers; i++)
+ readers[i]->Join();
+
+ // Stop time here.
+ MojoTimeTicks end_time = MojoGetTimeTicksNow();
+
+ // Add up write and read counts, and destroy the threads.
+ int64_t num_writes = 0;
+ for (unsigned i = 0; i < num_writers; i++) {
+ num_writes += writers[i]->num_writes();
+ delete writers[i];
+ }
+ writers.clear();
+ int64_t num_reads = 0;
+ for (unsigned i = 0; i < num_readers; i++) {
+ num_reads += readers[i]->num_reads();
+ delete readers[i];
+ }
+ readers.clear();
+
+ char test_name[200];
+ sprintf(test_name, "MessagePipe_Threaded_Writes_%uw_%ur_%ubytes",
+ num_writers, num_readers, static_cast<unsigned>(num_bytes));
+ mojo::test::LogPerfResult(test_name,
+ 1000000.0 * static_cast<double>(num_writes) /
+ (end_time - start_time),
+ "writes/second");
+ sprintf(test_name, "MessagePipe_Threaded_Reads_%uw_%ur_%ubytes",
+ num_writers, num_readers, static_cast<unsigned>(num_bytes));
+ mojo::test::LogPerfResult(test_name,
+ 1000000.0 * static_cast<double>(num_reads) /
+ (end_time - start_time),
+ "reads/second");
+ }
+#endif // !defined(WIN32)
+
MojoHandle h0_;
MojoHandle h1_;
@@ -67,6 +245,18 @@ class CorePerftest : public testing::Test {
uint32_t num_bytes_;
private:
+#if !defined(WIN32)
+ void Sleep(int64_t microseconds) {
+ struct timespec req = {
+ static_cast<time_t>(microseconds / 1000000), // Seconds.
+ static_cast<long>(microseconds % 1000000) * 1000L // Nanoseconds.
+ };
+ int rv MOJO_ALLOW_UNUSED;
+ rv = nanosleep(&req, NULL);
+ assert(rv == 0);
+ }
+#endif // !defined(WIN32)
+
MOJO_DISALLOW_COPY_AND_ASSIGN(CorePerftest);
};
@@ -122,4 +312,26 @@ TEST_F(CorePerftest, MessagePipe_EmptyRead) {
assert(result == MOJO_RESULT_OK);
}
+#if !defined(WIN32)
+TEST_F(CorePerftest, MessagePipe_Threaded) {
+ DoMessagePipeThreadedTest(1u, 1u, 100u);
+ DoMessagePipeThreadedTest(2u, 2u, 100u);
+ DoMessagePipeThreadedTest(3u, 3u, 100u);
+ DoMessagePipeThreadedTest(10u, 10u, 100u);
+ DoMessagePipeThreadedTest(10u, 1u, 100u);
+ DoMessagePipeThreadedTest(1u, 10u, 100u);
+
+ // For comparison of overhead:
+ DoMessagePipeThreadedTest(1u, 1u, 10u);
+ // 100 was done above.
+ DoMessagePipeThreadedTest(1u, 1u, 1000u);
+ DoMessagePipeThreadedTest(1u, 1u, 10000u);
+
+ DoMessagePipeThreadedTest(3u, 3u, 10u);
+ // 100 was done above.
+ DoMessagePipeThreadedTest(3u, 3u, 1000u);
+ DoMessagePipeThreadedTest(3u, 3u, 10000u);
+}
+#endif // !defined(WIN32)
+
} // namespace