diff options
author | viettrungluu@chromium.org <viettrungluu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-14 02:41:07 +0000 |
---|---|---|
committer | viettrungluu@chromium.org <viettrungluu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-14 02:41:07 +0000 |
commit | eca02f7bb37b96fabef1599779e66e883b7408d9 (patch) | |
tree | 1edc3cda152e4ebcc481cac9adc637b5c9e6a372 /mojo/public | |
parent | 50da19023478da22341f12be738c5881236c1ffe (diff) | |
download | chromium_src-eca02f7bb37b96fabef1599779e66e883b7408d9.zip chromium_src-eca02f7bb37b96fabef1599779e66e883b7408d9.tar.gz chromium_src-eca02f7bb37b96fabef1599779e66e883b7408d9.tar.bz2 |
Mojo: Add a threaded perf test for (local) message pipes.
R=sky@chromium.org
Review URL: https://codereview.chromium.org/164693002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@251235 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'mojo/public')
-rw-r--r-- | mojo/public/tests/system/core_perftest.cc | 212 | ||||
-rw-r--r-- | mojo/public/tests/test_support.h | 14 |
2 files changed, 226 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 diff --git a/mojo/public/tests/test_support.h b/mojo/public/tests/test_support.h index 32a54c9..e259456 100644 --- a/mojo/public/tests/test_support.h +++ b/mojo/public/tests/test_support.h @@ -22,4 +22,18 @@ MOJO_TEST_SUPPORT_EXPORT void MojoTestSupportLogPerfResult( } // extern "C" #endif +#ifdef __cplusplus +namespace mojo { +namespace test { + +inline void LogPerfResult(const char* test_name, + double value, + const char* units) { + MojoTestSupportLogPerfResult(test_name, value, units); +} + +} // namespace test +} // namespace mojo +#endif // __cplusplus + #endif // MOJO_PUBLIC_TESTS_TEST_SUPPORT_H_ |