| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors |
| // Licensed under the MIT License: |
| // |
| // Permission is hereby granted, free of charge, to any person obtaining a copy |
| // of this software and associated documentation files (the "Software"), to deal |
| // in the Software without restriction, including without limitation the rights |
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| // copies of the Software, and to permit persons to whom the Software is |
| // furnished to do so, subject to the following conditions: |
| // |
| // The above copyright notice and this permission notice shall be included in |
| // all copies or substantial portions of the Software. |
| // |
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| // THE SOFTWARE. |
| |
| #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 |