// Copyright (c) 2013, Kenton Varda <temporal@gmail.com> // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "common.h" namespace capnp { namespace benchmark { namespace null { uint64_t arena[1024*1024]; uint64_t* arenaPos = arena; template <typename T> T* allocate(int count = 1) { T* result = reinterpret_cast<T*>(arenaPos); arenaPos += (sizeof(T) * count + 7) / 8; if (arenaPos > arena + sizeof(arena) / sizeof(arena[0])) { throw std::bad_alloc(); } return result; } char* copyString(const char* str) { size_t len = strlen(str); char* result = allocate<char>(len); memcpy(result, str, len + 1); return result; } template <typename T> struct List { size_t size; T* items; inline T* begin() const { return items; } inline T* end() const { return items + size; } inline List<T>& init(size_t size) { this->size = size; items = allocate<T>(size); return *this; } }; // ======================================================================================= struct SingleUseObjects { class ObjectSizeCounter { public: ObjectSizeCounter(uint64_t iters): counter(0) {} void add(uint64_t wordCount) { counter += wordCount; } uint64_t get() { return counter; } private: uint64_t counter; }; }; struct ReusableObjects { class ObjectSizeCounter { public: ObjectSizeCounter(uint64_t iters): iters(iters), maxSize(0) {} void add(size_t wordCount) { maxSize = std::max(wordCount, maxSize); } uint64_t get() { return iters * maxSize; } private: uint64_t iters; size_t maxSize; }; }; // ======================================================================================= template <typename TestCase, typename ReuseStrategy, typename Compression> struct BenchmarkMethods { static uint64_t syncClient(int inputFd, int outputFd, uint64_t iters) { fprintf(stderr, "Null benchmark doesn't do I/O.\n"); exit(1); } static uint64_t asyncClientSender( int outputFd, ProducerConsumerQueue<typename TestCase::Expectation>* expectations, uint64_t iters) { fprintf(stderr, "Null benchmark doesn't do I/O.\n"); exit(1); } static void asyncClientReceiver( int inputFd, ProducerConsumerQueue<typename TestCase::Expectation>* expectations, uint64_t iters) { fprintf(stderr, "Null benchmark doesn't do I/O.\n"); exit(1); } static uint64_t asyncClient(int inputFd, int outputFd, uint64_t iters) { fprintf(stderr, "Null benchmark doesn't do I/O.\n"); exit(1); } static uint64_t server(int inputFd, int outputFd, uint64_t iters) { fprintf(stderr, "Null benchmark doesn't do I/O.\n"); exit(1); } static uint64_t passByObject(uint64_t iters, bool countObjectSize) { typename ReuseStrategy::ObjectSizeCounter sizeCounter(iters); for (; iters > 0; --iters) { arenaPos = arena; typename TestCase::Request request; typename TestCase::Expectation expected = TestCase::setupRequest(&request); typename TestCase::Response response; TestCase::handleRequest(request, &response); if (!TestCase::checkResponse(response, expected)) { throw std::logic_error("Incorrect response."); } sizeCounter.add((arenaPos - arena) * sizeof(arena[0])); } return sizeCounter.get(); } static uint64_t passByBytes(uint64_t iters) { fprintf(stderr, "Null benchmark doesn't do I/O.\n"); exit(1); } }; struct BenchmarkTypes { typedef void Uncompressed; typedef void Packed; #if HAVE_SNAPPY typedef void SnappyCompressed; #endif // HAVE_SNAPPY typedef ReusableObjects ReusableResources; typedef SingleUseObjects SingleUseResources; template <typename TestCase, typename ReuseStrategy, typename Compression> struct BenchmarkMethods: public null::BenchmarkMethods<TestCase, ReuseStrategy, Compression> {}; }; } // namespace null } // namespace benchmark } // namespace capnp