15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file.
45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// This tests the performance of the C API.
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "mojo/public/c/system/core.h"
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <assert.h>
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <stddef.h>
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <stdint.h>
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <stdio.h>
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
14effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "mojo/public/cpp/system/macros.h"
15e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "mojo/public/cpp/test_support/test_support.h"
16e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "mojo/public/cpp/test_support/test_utils.h"
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// TODO(vtl): (here and below) crbug.com/342893
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if !defined(WIN32)
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <time.h>
22effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "mojo/public/cpp/utility/thread.h"
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif  // !defined(WIN32)
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace {
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if !defined(WIN32)
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class MessagePipeWriterThread : public mojo::Thread {
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MessagePipeWriterThread(MojoHandle handle, uint32_t num_bytes)
316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      : handle_(handle), num_bytes_(num_bytes), num_writes_(0) {}
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual ~MessagePipeWriterThread() {}
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void Run() MOJO_OVERRIDE {
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    char buffer[10000];
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    assert(num_bytes_ <= sizeof(buffer));
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // TODO(vtl): Should I throttle somehow?
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    for (;;) {
406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      MojoResult result = MojoWriteMessage(
416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          handle_, buffer, num_bytes_, NULL, 0, MOJO_WRITE_MESSAGE_FLAG_NONE);
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (result == MOJO_RESULT_OK) {
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        num_writes_++;
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        continue;
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // We failed to write.
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // Either |handle_| or its peer was closed.
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      assert(result == MOJO_RESULT_INVALID_ARGUMENT ||
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)             result == MOJO_RESULT_FAILED_PRECONDITION);
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      break;
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Use only after joining the thread.
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int64_t num_writes() const { return num_writes_; }
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const MojoHandle handle_;
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const uint32_t num_bytes_;
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int64_t num_writes_;
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MOJO_DISALLOW_COPY_AND_ASSIGN(MessagePipeWriterThread);
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class MessagePipeReaderThread : public mojo::Thread {
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  explicit MessagePipeReaderThread(MojoHandle handle)
696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      : handle_(handle), num_reads_(0) {}
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual ~MessagePipeReaderThread() {}
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void Run() MOJO_OVERRIDE {
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    char buffer[10000];
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    for (;;) {
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      uint32_t num_bytes = static_cast<uint32_t>(sizeof(buffer));
776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      MojoResult result = MojoReadMessage(
786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          handle_, buffer, &num_bytes, NULL, NULL, MOJO_READ_MESSAGE_FLAG_NONE);
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (result == MOJO_RESULT_OK) {
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        num_reads_++;
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        continue;
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (result == MOJO_RESULT_SHOULD_WAIT) {
856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        result = MojoWait(
866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            handle_, MOJO_HANDLE_SIGNAL_READABLE, MOJO_DEADLINE_INDEFINITE);
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (result == MOJO_RESULT_OK) {
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          // Go to the top of the loop to read again.
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          continue;
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        }
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // We failed to read and possibly failed to wait.
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // Either |handle_| or its peer was closed.
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      assert(result == MOJO_RESULT_INVALID_ARGUMENT ||
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)             result == MOJO_RESULT_FAILED_PRECONDITION);
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      break;
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Use only after joining the thread.
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int64_t num_reads() const { return num_reads_; }
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const MojoHandle handle_;
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int64_t num_reads_;
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MOJO_DISALLOW_COPY_AND_ASSIGN(MessagePipeReaderThread);
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif  // !defined(WIN32)
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class CorePerftest : public testing::Test {
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CorePerftest() : buffer_(NULL), num_bytes_(0) {}
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual ~CorePerftest() {}
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  static void NoOp(void* /*closure*/) {}
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  static void MessagePipe_CreateAndClose(void* closure) {
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CorePerftest* self = static_cast<CorePerftest*>(closure);
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    MojoResult result MOJO_ALLOW_UNUSED;
122f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    result = MojoCreateMessagePipe(NULL, &self->h0_, &self->h1_);
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    assert(result == MOJO_RESULT_OK);
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    result = MojoClose(self->h0_);
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    assert(result == MOJO_RESULT_OK);
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    result = MojoClose(self->h1_);
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    assert(result == MOJO_RESULT_OK);
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  static void MessagePipe_WriteAndRead(void* closure) {
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CorePerftest* self = static_cast<CorePerftest*>(closure);
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    MojoResult result MOJO_ALLOW_UNUSED;
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    result = MojoWriteMessage(self->h0_,
1346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                              self->buffer_,
1356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                              self->num_bytes_,
1366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                              NULL,
1376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                              0,
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              MOJO_WRITE_MESSAGE_FLAG_NONE);
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    assert(result == MOJO_RESULT_OK);
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    uint32_t read_bytes = self->num_bytes_;
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    result = MojoReadMessage(self->h1_,
1426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                             self->buffer_,
1436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                             &read_bytes,
1446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                             NULL,
1456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                             NULL,
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             MOJO_READ_MESSAGE_FLAG_NONE);
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    assert(result == MOJO_RESULT_OK);
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  static void MessagePipe_EmptyRead(void* closure) {
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CorePerftest* self = static_cast<CorePerftest*>(closure);
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    MojoResult result MOJO_ALLOW_UNUSED;
1536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    result = MojoReadMessage(
1546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        self->h0_, NULL, NULL, NULL, NULL, MOJO_READ_MESSAGE_FLAG_MAY_DISCARD);
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    assert(result == MOJO_RESULT_SHOULD_WAIT);
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) protected:
1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if !defined(WIN32)
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void DoMessagePipeThreadedTest(unsigned num_writers,
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 unsigned num_readers,
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 uint32_t num_bytes) {
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    static const int64_t kPerftestTimeMicroseconds = 3 * 1000000;
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    assert(num_writers > 0);
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    assert(num_readers > 0);
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    MojoResult result MOJO_ALLOW_UNUSED;
169f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    result = MojoCreateMessagePipe(NULL, &h0_, &h1_);
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    assert(result == MOJO_RESULT_OK);
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    std::vector<MessagePipeWriterThread*> writers;
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    for (unsigned i = 0; i < num_writers; i++)
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      writers.push_back(new MessagePipeWriterThread(h0_, num_bytes));
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    std::vector<MessagePipeReaderThread*> readers;
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    for (unsigned i = 0; i < num_readers; i++)
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      readers.push_back(new MessagePipeReaderThread(h1_));
1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Start time here, just before we fire off the threads.
1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const MojoTimeTicks start_time = MojoGetTimeTicksNow();
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Interleave the starts.
1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    for (unsigned i = 0; i < num_writers || i < num_readers; i++) {
1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (i < num_writers)
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        writers[i]->Start();
1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (i < num_readers)
1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        readers[i]->Start();
1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Sleep(kPerftestTimeMicroseconds);
1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Close both handles to make writers and readers stop immediately.
1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    result = MojoClose(h0_);
1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    assert(result == MOJO_RESULT_OK);
1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    result = MojoClose(h1_);
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    assert(result == MOJO_RESULT_OK);
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Join everything.
2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    for (unsigned i = 0; i < num_writers; i++)
2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      writers[i]->Join();
2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    for (unsigned i = 0; i < num_readers; i++)
2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      readers[i]->Join();
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Stop time here.
2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    MojoTimeTicks end_time = MojoGetTimeTicksNow();
2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Add up write and read counts, and destroy the threads.
2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int64_t num_writes = 0;
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    for (unsigned i = 0; i < num_writers; i++) {
2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      num_writes += writers[i]->num_writes();
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      delete writers[i];
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    writers.clear();
2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int64_t num_reads = 0;
2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    for (unsigned i = 0; i < num_readers; i++) {
2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      num_reads += readers[i]->num_reads();
2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      delete readers[i];
2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    readers.clear();
2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    char test_name[200];
2236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    sprintf(test_name,
2246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            "MessagePipe_Threaded_Writes_%uw_%ur_%ubytes",
2256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            num_writers,
2266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            num_readers,
2276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            static_cast<unsigned>(num_bytes));
2286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    mojo::test::LogPerfResult(
2296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        test_name,
2306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        1000000.0 * static_cast<double>(num_writes) / (end_time - start_time),
2316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        "writes/second");
2326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    sprintf(test_name,
2336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            "MessagePipe_Threaded_Reads_%uw_%ur_%ubytes",
2346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            num_writers,
2356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            num_readers,
2366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            static_cast<unsigned>(num_bytes));
2376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    mojo::test::LogPerfResult(
2386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        test_name,
2396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        1000000.0 * static_cast<double>(num_reads) / (end_time - start_time),
2406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        "reads/second");
2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif  // !defined(WIN32)
2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MojoHandle h0_;
2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MojoHandle h1_;
2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void* buffer_;
2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  uint32_t num_bytes_;
2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if !defined(WIN32)
2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void Sleep(int64_t microseconds) {
2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    struct timespec req = {
2546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        static_cast<time_t>(microseconds / 1000000),       // Seconds.
2556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        static_cast<long>(microseconds % 1000000) * 1000L  // Nanoseconds.
2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    };
2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int rv MOJO_ALLOW_UNUSED;
2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    rv = nanosleep(&req, NULL);
2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    assert(rv == 0);
2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif  // !defined(WIN32)
2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MOJO_DISALLOW_COPY_AND_ASSIGN(CorePerftest);
2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// A no-op test so we can compare performance.
2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(CorePerftest, NoOp) {
2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  mojo::test::IterateAndReportPerf("NoOp", &CorePerftest::NoOp, this);
2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(CorePerftest, MessagePipe_CreateAndClose) {
2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  mojo::test::IterateAndReportPerf("MessagePipe_CreateAndClose",
2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   &CorePerftest::MessagePipe_CreateAndClose,
2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   this);
2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(CorePerftest, MessagePipe_WriteAndRead) {
2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MojoResult result MOJO_ALLOW_UNUSED;
279f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  result = MojoCreateMessagePipe(NULL, &h0_, &h1_);
2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  assert(result == MOJO_RESULT_OK);
2816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  char buffer[10000] = {0};
2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  buffer_ = buffer;
2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  num_bytes_ = 10u;
2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  mojo::test::IterateAndReportPerf("MessagePipe_WriteAndRead_10bytes",
2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   &CorePerftest::MessagePipe_WriteAndRead,
2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   this);
2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  num_bytes_ = 100u;
2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  mojo::test::IterateAndReportPerf("MessagePipe_WriteAndRead_100bytes",
2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   &CorePerftest::MessagePipe_WriteAndRead,
2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   this);
2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  num_bytes_ = 1000u;
2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  mojo::test::IterateAndReportPerf("MessagePipe_WriteAndRead_1000bytes",
2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   &CorePerftest::MessagePipe_WriteAndRead,
2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   this);
2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  num_bytes_ = 10000u;
2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  mojo::test::IterateAndReportPerf("MessagePipe_WriteAndRead_10000bytes",
2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   &CorePerftest::MessagePipe_WriteAndRead,
2985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   this);
2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  result = MojoClose(h0_);
3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  assert(result == MOJO_RESULT_OK);
3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  result = MojoClose(h1_);
3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  assert(result == MOJO_RESULT_OK);
3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(CorePerftest, MessagePipe_EmptyRead) {
3065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MojoResult result MOJO_ALLOW_UNUSED;
307f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  result = MojoCreateMessagePipe(NULL, &h0_, &h1_);
3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  assert(result == MOJO_RESULT_OK);
3096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  mojo::test::IterateAndReportPerf(
3106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      "MessagePipe_EmptyRead", &CorePerftest::MessagePipe_EmptyRead, this);
3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  result = MojoClose(h0_);
3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  assert(result == MOJO_RESULT_OK);
3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  result = MojoClose(h1_);
3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  assert(result == MOJO_RESULT_OK);
3155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if !defined(WIN32)
3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(CorePerftest, MessagePipe_Threaded) {
3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DoMessagePipeThreadedTest(1u, 1u, 100u);
3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DoMessagePipeThreadedTest(2u, 2u, 100u);
3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DoMessagePipeThreadedTest(3u, 3u, 100u);
3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DoMessagePipeThreadedTest(10u, 10u, 100u);
3235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DoMessagePipeThreadedTest(10u, 1u, 100u);
3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DoMessagePipeThreadedTest(1u, 10u, 100u);
3255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // For comparison of overhead:
3275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DoMessagePipeThreadedTest(1u, 1u, 10u);
3285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // 100 was done above.
3295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DoMessagePipeThreadedTest(1u, 1u, 1000u);
3305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DoMessagePipeThreadedTest(1u, 1u, 10000u);
3315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DoMessagePipeThreadedTest(3u, 3u, 10u);
3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // 100 was done above.
3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DoMessagePipeThreadedTest(3u, 3u, 1000u);
3355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DoMessagePipeThreadedTest(3u, 3u, 10000u);
3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif  // !defined(WIN32)
3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace
340