This source file includes following definitions.
- num_writes_
- Run
- num_writes
- num_reads_
- Run
- num_reads
- num_bytes_
- NoOp
- MessagePipe_CreateAndClose
- MessagePipe_WriteAndRead
- MessagePipe_EmptyRead
- DoMessagePipeThreadedTest
- Sleep
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
#include "mojo/public/c/system/core.h"
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include "mojo/public/cpp/system/macros.h"
#include "mojo/public/cpp/test_support/test_support.h"
#include "mojo/public/cpp/test_support/test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
#if !defined(WIN32)
#include <time.h>
#include "mojo/public/cpp/utility/thread.h"
#endif
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));
for (;;) {
MojoResult result = MojoWriteMessage(handle_, buffer, num_bytes_, NULL, 0,
MOJO_WRITE_MESSAGE_FLAG_NONE);
if (result == MOJO_RESULT_OK) {
num_writes_++;
continue;
}
assert(result == MOJO_RESULT_INVALID_ARGUMENT ||
result == MOJO_RESULT_FAILED_PRECONDITION);
break;
}
}
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) {
continue;
}
}
assert(result == MOJO_RESULT_INVALID_ARGUMENT ||
result == MOJO_RESULT_FAILED_PRECONDITION);
break;
}
}
int64_t num_reads() const { return num_reads_; }
private:
const MojoHandle handle_;
int64_t num_reads_;
MOJO_DISALLOW_COPY_AND_ASSIGN(MessagePipeReaderThread);
};
#endif
class CorePerftest : public testing::Test {
public:
CorePerftest() : buffer_(NULL), num_bytes_(0) {}
virtual ~CorePerftest() {}
static void NoOp(void* ) {
}
static void MessagePipe_CreateAndClose(void* closure) {
CorePerftest* self = static_cast<CorePerftest*>(closure);
MojoResult result MOJO_ALLOW_UNUSED;
result = MojoCreateMessagePipe(&self->h0_, &self->h1_);
assert(result == MOJO_RESULT_OK);
result = MojoClose(self->h0_);
assert(result == MOJO_RESULT_OK);
result = MojoClose(self->h1_);
assert(result == MOJO_RESULT_OK);
}
static void MessagePipe_WriteAndRead(void* closure) {
CorePerftest* self = static_cast<CorePerftest*>(closure);
MojoResult result MOJO_ALLOW_UNUSED;
result = MojoWriteMessage(self->h0_,
self->buffer_, self->num_bytes_,
NULL, 0,
MOJO_WRITE_MESSAGE_FLAG_NONE);
assert(result == MOJO_RESULT_OK);
uint32_t read_bytes = self->num_bytes_;
result = MojoReadMessage(self->h1_,
self->buffer_, &read_bytes,
NULL, NULL,
MOJO_READ_MESSAGE_FLAG_NONE);
assert(result == MOJO_RESULT_OK);
}
static void MessagePipe_EmptyRead(void* closure) {
CorePerftest* self = static_cast<CorePerftest*>(closure);
MojoResult result MOJO_ALLOW_UNUSED;
result = MojoReadMessage(self->h0_,
NULL, NULL,
NULL, NULL,
MOJO_READ_MESSAGE_FLAG_MAY_DISCARD);
assert(result == MOJO_RESULT_SHOULD_WAIT);
}
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_));
const MojoTimeTicks start_time = MojoGetTimeTicksNow();
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);
result = MojoClose(h0_);
assert(result == MOJO_RESULT_OK);
result = MojoClose(h1_);
assert(result == MOJO_RESULT_OK);
for (unsigned i = 0; i < num_writers; i++)
writers[i]->Join();
for (unsigned i = 0; i < num_readers; i++)
readers[i]->Join();
MojoTimeTicks end_time = MojoGetTimeTicksNow();
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
MojoHandle h0_;
MojoHandle h1_;
void* buffer_;
uint32_t num_bytes_;
private:
#if !defined(WIN32)
void Sleep(int64_t microseconds) {
struct timespec req = {
static_cast<time_t>(microseconds / 1000000),
static_cast<long>(microseconds % 1000000) * 1000L
};
int rv MOJO_ALLOW_UNUSED;
rv = nanosleep(&req, NULL);
assert(rv == 0);
}
#endif
MOJO_DISALLOW_COPY_AND_ASSIGN(CorePerftest);
};
TEST_F(CorePerftest, NoOp) {
mojo::test::IterateAndReportPerf("NoOp", &CorePerftest::NoOp, this);
}
TEST_F(CorePerftest, MessagePipe_CreateAndClose) {
mojo::test::IterateAndReportPerf("MessagePipe_CreateAndClose",
&CorePerftest::MessagePipe_CreateAndClose,
this);
}
TEST_F(CorePerftest, MessagePipe_WriteAndRead) {
MojoResult result MOJO_ALLOW_UNUSED;
result = MojoCreateMessagePipe(&h0_, &h1_);
assert(result == MOJO_RESULT_OK);
char buffer[10000] = { 0 };
buffer_ = buffer;
num_bytes_ = 10u;
mojo::test::IterateAndReportPerf("MessagePipe_WriteAndRead_10bytes",
&CorePerftest::MessagePipe_WriteAndRead,
this);
num_bytes_ = 100u;
mojo::test::IterateAndReportPerf("MessagePipe_WriteAndRead_100bytes",
&CorePerftest::MessagePipe_WriteAndRead,
this);
num_bytes_ = 1000u;
mojo::test::IterateAndReportPerf("MessagePipe_WriteAndRead_1000bytes",
&CorePerftest::MessagePipe_WriteAndRead,
this);
num_bytes_ = 10000u;
mojo::test::IterateAndReportPerf("MessagePipe_WriteAndRead_10000bytes",
&CorePerftest::MessagePipe_WriteAndRead,
this);
result = MojoClose(h0_);
assert(result == MOJO_RESULT_OK);
result = MojoClose(h1_);
assert(result == MOJO_RESULT_OK);
}
TEST_F(CorePerftest, MessagePipe_EmptyRead) {
MojoResult result MOJO_ALLOW_UNUSED;
result = MojoCreateMessagePipe(&h0_, &h1_);
assert(result == MOJO_RESULT_OK);
mojo::test::IterateAndReportPerf("MessagePipe_EmptyRead",
&CorePerftest::MessagePipe_EmptyRead,
this);
result = MojoClose(h0_);
assert(result == MOJO_RESULT_OK);
result = MojoClose(h1_);
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);
DoMessagePipeThreadedTest(1u, 1u, 10u);
DoMessagePipeThreadedTest(1u, 1u, 1000u);
DoMessagePipeThreadedTest(1u, 1u, 10000u);
DoMessagePipeThreadedTest(3u, 3u, 10u);
DoMessagePipeThreadedTest(3u, 3u, 1000u);
DoMessagePipeThreadedTest(3u, 3u, 10000u);
}
#endif
}