diff options
author | Henning Baldersheim <balder@yahoo-inc.com> | 2022-05-19 21:57:59 +0000 |
---|---|---|
committer | Henning Baldersheim <balder@yahoo-inc.com> | 2022-05-20 12:38:48 +0000 |
commit | 64500ab17deb86b394edc81f4ad42b5a2c43fe30 (patch) | |
tree | 64334ba1513b697dacd5068981a8ee5b7ad92f3b /vespalib/src/tests/benchmark | |
parent | cfa6ec5cdbd1cf39558d3f85101de05230d6c225 (diff) |
Fold staging_vespalib into vespalib
Diffstat (limited to 'vespalib/src/tests/benchmark')
-rw-r--r-- | vespalib/src/tests/benchmark/.gitignore | 4 | ||||
-rw-r--r-- | vespalib/src/tests/benchmark/CMakeLists.txt | 12 | ||||
-rw-r--r-- | vespalib/src/tests/benchmark/benchmark.cpp | 30 | ||||
-rwxr-xr-x | vespalib/src/tests/benchmark/benchmark_test.sh | 21 | ||||
-rw-r--r-- | vespalib/src/tests/benchmark/testbase.cpp | 279 | ||||
-rw-r--r-- | vespalib/src/tests/benchmark/testbase.h | 168 |
6 files changed, 514 insertions, 0 deletions
diff --git a/vespalib/src/tests/benchmark/.gitignore b/vespalib/src/tests/benchmark/.gitignore new file mode 100644 index 00000000000..3280cb17888 --- /dev/null +++ b/vespalib/src/tests/benchmark/.gitignore @@ -0,0 +1,4 @@ +.depend +Makefile +benchmark_test +vespalib_benchmark_test_app diff --git a/vespalib/src/tests/benchmark/CMakeLists.txt b/vespalib/src/tests/benchmark/CMakeLists.txt new file mode 100644 index 00000000000..7003a5c4183 --- /dev/null +++ b/vespalib/src/tests/benchmark/CMakeLists.txt @@ -0,0 +1,12 @@ +# Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +vespa_add_executable(vespalib_benchmark_test_app + SOURCES + benchmark.cpp + testbase.cpp + DEPENDS + vespalib + EXTERNAL_DEPENDS + ${VESPA_GLIBC_RT_LIB} +) +vespa_add_test(NAME vespalib_benchmark_test NO_VALGRIND COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/benchmark_test.sh BENCHMARK + DEPENDS vespalib_benchmark_test_app) diff --git a/vespalib/src/tests/benchmark/benchmark.cpp b/vespalib/src/tests/benchmark/benchmark.cpp new file mode 100644 index 00000000000..f1e69758c8c --- /dev/null +++ b/vespalib/src/tests/benchmark/benchmark.cpp @@ -0,0 +1,30 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +#include <vespa/vespalib/testkit/testapp.h> +#include "testbase.h" + +#include <vespa/log/log.h> +LOG_SETUP("benchmark_test"); + +using namespace vespalib; + +TEST_SETUP(Test) + +int +Test::Main() +{ + TEST_INIT("benchmark_test"); + + if (_argc > 1) { + size_t concurrency(1); + size_t numRuns(1000); + if (_argc > 2) { + numRuns = strtoul(_argv[2], NULL, 0); + if (_argc > 3) { + concurrency = strtoul(_argv[3], NULL, 0); + } + } + Benchmark::run(_argv[1], numRuns, concurrency); + } + + TEST_DONE(); +} diff --git a/vespalib/src/tests/benchmark/benchmark_test.sh b/vespalib/src/tests/benchmark/benchmark_test.sh new file mode 100755 index 00000000000..28dc6b518be --- /dev/null +++ b/vespalib/src/tests/benchmark/benchmark_test.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +set -e +TIME=time + +$TIME ./vespalib_benchmark_test_app vespalib::ParamByReferenceVectorInt 200000 1 +$TIME ./vespalib_benchmark_test_app vespalib::ParamByValueVectorInt 4000 1 +$TIME ./vespalib_benchmark_test_app vespalib::ParamByReferenceVectorString 30000 1 +$TIME ./vespalib_benchmark_test_app vespalib::ParamByValueVectorString 40 1 +$TIME ./vespalib_benchmark_test_app vespalib::ReturnByReferenceVectorString 10 1 +$TIME ./vespalib_benchmark_test_app vespalib::ReturnByValueVectorString 10 1 +$TIME ./vespalib_benchmark_test_app vespalib::ReturnByValueMultiVectorString 10 1 +$TIME ./vespalib_benchmark_test_app vespalib::ClockSystem 1000 1 +$TIME ./vespalib_benchmark_test_app vespalib::ClockGToD 1000 1 +$TIME ./vespalib_benchmark_test_app vespalib::ClockGToD 20000 1 +$TIME ./vespalib_benchmark_test_app vespalib::ClockREALTIME 1000 1 +$TIME ./vespalib_benchmark_test_app vespalib::ClockMONOTONIC 1000 1 +$TIME ./vespalib_benchmark_test_app vespalib::ClockMONOTONIC_RAW 1000 1 +$TIME ./vespalib_benchmark_test_app vespalib::ClockPROCESS_CPUTIME_ID 2500 1 +$TIME ./vespalib_benchmark_test_app vespalib::ClockTHREAD_CPUTIME_ID 2500 1 +$TIME ./vespalib_benchmark_test_app vespalib::CreateVespalibString 20000 1 diff --git a/vespalib/src/tests/benchmark/testbase.cpp b/vespalib/src/tests/benchmark/testbase.cpp new file mode 100644 index 00000000000..6b5f8d7d627 --- /dev/null +++ b/vespalib/src/tests/benchmark/testbase.cpp @@ -0,0 +1,279 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +#include "testbase.h" +#include <vespa/vespalib/util/time.h> +#include <cassert> + +#include <vespa/log/log.h> +LOG_SETUP(".testbase"); + +using namespace std::chrono; + +namespace vespalib { + +IMPLEMENT_IDENTIFIABLE_ABSTRACT_NS(vespalib, Benchmark, Identifiable); + +IMPLEMENT_BENCHMARK(ParamByReferenceVectorInt, Benchmark); +IMPLEMENT_BENCHMARK(ParamByValueVectorInt, Benchmark); +IMPLEMENT_BENCHMARK(ParamByReferenceVectorString, Benchmark); +IMPLEMENT_BENCHMARK(ParamByValueVectorString, Benchmark); +IMPLEMENT_BENCHMARK(ReturnByReferenceVectorString, Benchmark); +IMPLEMENT_BENCHMARK(ReturnByValueVectorString, Benchmark); +IMPLEMENT_BENCHMARK(ReturnByValueMultiVectorString, Benchmark); +IMPLEMENT_BENCHMARK(ClockSystem, Benchmark); +IMPLEMENT_BENCHMARK(ClockREALTIME, Benchmark); +IMPLEMENT_BENCHMARK(ClockMONOTONIC, Benchmark); +IMPLEMENT_BENCHMARK(ClockMONOTONIC_RAW, Benchmark); +IMPLEMENT_BENCHMARK(ClockPROCESS_CPUTIME_ID, Benchmark); +IMPLEMENT_BENCHMARK(ClockTHREAD_CPUTIME_ID, Benchmark); +IMPLEMENT_BENCHMARK(CreateVespalibString, Benchmark); + +void Benchmark::run(const char *name, size_t numRuns, size_t concurrency) +{ + const Identifiable::RuntimeClass * cInfo = Identifiable::classFromName(name); + if (cInfo) { + std::unique_ptr<Benchmark> test(static_cast<Benchmark *>(cInfo->create())); + test->run(numRuns, concurrency); + } else { + LOG(warning, "Could not find any test with the name %s", name); + } +} +void Benchmark::run(size_t numRuns, size_t concurrency) +{ + LOG(info, "Starting benchmark %s with %ld threads and %ld rep", getClass().name(), concurrency, numRuns); + for (size_t i(0); i < numRuns; i++) { + onRun(); + } + LOG(info, "Stopping benchmark %s", getClass().name()); +} + +size_t ParamByReferenceVectorInt::callByReference(const Vector & values) const +{ + return values.size(); +} + +size_t ParamByReferenceVectorInt::onRun() +{ + Vector values(1000); + size_t sum(0); + for (size_t i=0; i < 1000; i++) { + sum += callByReference(values); + } + return sum; +} + +size_t ParamByValueVectorInt::callByValue(Vector values) const +{ + return values.size(); +} + +size_t ParamByValueVectorInt::onRun() +{ + Vector values(1000); + size_t sum(0); + for (size_t i=0; i < 1000; i++) { + sum += callByValue(values); + } + return sum; +} + +size_t ParamByReferenceVectorString::callByReference(const Vector & values) const +{ + return values.size(); +} + +size_t ParamByReferenceVectorString::onRun() +{ + Vector values(1000, "This is a simple string copy test"); + size_t sum(0); + for (size_t i=0; i < 1000; i++) { + sum += callByReference(values); + } + return sum; +} + +size_t ParamByValueVectorString::callByValue(Vector values) const +{ + return values.size(); +} + +size_t ParamByValueVectorString::onRun() +{ + Vector values(1000, "This is a simple string copy test"); + size_t sum(0); + for (size_t i=0; i < 1000; i++) { + sum += callByValue(values); + } + return sum; +} + +const ReturnByReferenceVectorString::Vector & ReturnByReferenceVectorString::returnByReference(Vector & param) const +{ + Vector values(1000, "return by value"); + param.swap(values); + return param; +} + +size_t ReturnByReferenceVectorString::onRun() +{ + size_t sum(0); + for (size_t i=0; i < 1000; i++) { + Vector values; + sum += returnByReference(values).size(); + } + return sum; +} + +ReturnByValueVectorString::Vector ReturnByValueVectorString::returnByValue() const +{ + Vector values; + if (rand() % 7) { + Vector tmp(1000, "return by value"); + values.swap(tmp); + } else { + Vector tmp(1000, "Return by value"); + values.swap(tmp); + } + return values; +} + +size_t ReturnByValueVectorString::onRun() +{ + size_t sum(0); + for (size_t i=0; i < 1000; i++) { + sum += returnByValue().size(); + } + return sum; +} + +ReturnByValueMultiVectorString::Vector ReturnByValueMultiVectorString::returnByValue() const +{ + if (rand() % 7) { + Vector values(1000, "return by value"); + return values; + } else { + Vector values(1000, "Return by value"); + return values; + } +} + +size_t ReturnByValueMultiVectorString::onRun() +{ + size_t sum(0); + for (size_t i=0; i < 1000; i++) { + sum += returnByValue().size(); + } + return sum; +} + +size_t ClockSystem::onRun() +{ + vespalib::system_time start(vespalib::system_clock::now()); + vespalib::system_time end(start); + for (size_t i=0; i < 1000; i++) { + end = vespalib::system_clock::now(); + } + return std::chrono::duration_cast<std::chrono::nanoseconds>(start - end).count(); +} + +size_t ClockREALTIME::onRun() +{ + struct timespec ts; + int foo = clock_gettime(CLOCK_REALTIME, &ts); + assert(foo == 0); + (void) foo; + nanoseconds start(ts.tv_sec*1000L*1000L*1000L + ts.tv_nsec); + nanoseconds end(start); + for (size_t i=0; i < 1000; i++) { + clock_gettime(CLOCK_REALTIME, &ts); + end = nanoseconds(ts.tv_sec*1000L*1000L*1000L + ts.tv_nsec); + } + return count_ns(start - end); +} + +size_t ClockMONOTONIC::onRun() +{ + struct timespec ts; + int foo = clock_gettime(CLOCK_MONOTONIC, &ts); + assert(foo == 0); + (void) foo; + nanoseconds start(ts.tv_sec*1000L*1000L*1000L + ts.tv_nsec); + nanoseconds end(start); + for (size_t i=0; i < 1000; i++) { + clock_gettime(CLOCK_MONOTONIC, &ts); + end = nanoseconds(ts.tv_sec*1000L*1000L*1000L + ts.tv_nsec); + } + return count_ns(start - end);; +} + +ClockMONOTONIC_RAW::ClockMONOTONIC_RAW() +{ +#ifndef CLOCK_MONOTONIC_RAW + LOG(warning, "CLOCK_MONOTONIC_RAW is not defined, using CLOCK_MONOTONIC instead."); +#endif +} + +#ifndef CLOCK_MONOTONIC_RAW + #define CLOCK_MONOTONIC_RAW CLOCK_MONOTONIC +#endif + +size_t ClockMONOTONIC_RAW::onRun() +{ + struct timespec ts; + int foo = clock_gettime(CLOCK_MONOTONIC_RAW, &ts); + assert(foo == 0); + (void) foo; + nanoseconds start(ts.tv_sec*1000L*1000L*1000L + ts.tv_nsec); + nanoseconds end(start); + for (size_t i=0; i < 1000; i++) { + clock_gettime(CLOCK_MONOTONIC_RAW, &ts); + end = nanoseconds(ts.tv_sec*1000L*1000L*1000L + ts.tv_nsec); + } + return count_ns(start - end); +} + +size_t ClockPROCESS_CPUTIME_ID::onRun() +{ + struct timespec ts; + int foo = clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts); + assert(foo == 0); + (void) foo; + nanoseconds start(ts.tv_sec*1000L*1000L*1000L + ts.tv_nsec); + nanoseconds end(start); + for (size_t i=0; i < 1000; i++) { + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts); + end =nanoseconds(ts.tv_sec*1000L*1000L*1000L + ts.tv_nsec); + } + return count_ns(start - end); +} + +size_t ClockTHREAD_CPUTIME_ID::onRun() +{ + struct timespec ts; + int foo = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts); + assert(foo == 0); + (void) foo; + nanoseconds start(ts.tv_sec*1000L*1000L*1000L + ts.tv_nsec); + nanoseconds end(start); + for (size_t i=0; i < 1000; i++) { + clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts); + end = nanoseconds(ts.tv_sec*1000L*1000L*1000L + ts.tv_nsec); + } + return count_ns(start - end); +} + +size_t CreateVespalibString::onRun() +{ + size_t sum(0); + const char * text1("Dette er en passe"); + const char * text2(" kort streng som passer paa stacken"); + char text[100]; + strcpy(text, text1); + strcat(text, text2); + for (size_t i=0; i < 1000; i++) { + string s(text); + sum += s.size(); + } + return sum; +} + +} diff --git a/vespalib/src/tests/benchmark/testbase.h b/vespalib/src/tests/benchmark/testbase.h new file mode 100644 index 00000000000..95621f52471 --- /dev/null +++ b/vespalib/src/tests/benchmark/testbase.h @@ -0,0 +1,168 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +#pragma once + +#include <vespa/vespalib/objects/identifiable.h> +#include <vector> +#include <string> + +#define BENCHMARK_BASE_CID(n) (0x1000000 + n) + +#define CID_vespalib_Benchmark BENCHMARK_BASE_CID(0) +#define CID_vespalib_ParamByReferenceVectorInt BENCHMARK_BASE_CID(1) +#define CID_vespalib_ParamByReferenceVectorString BENCHMARK_BASE_CID(2) +#define CID_vespalib_ParamByValueVectorInt BENCHMARK_BASE_CID(3) +#define CID_vespalib_ParamByValueVectorString BENCHMARK_BASE_CID(4) +#define CID_vespalib_ReturnByReferenceVectorString BENCHMARK_BASE_CID(5) +#define CID_vespalib_ReturnByValueVectorString BENCHMARK_BASE_CID(6) +#define CID_vespalib_ReturnByValueMultiVectorString BENCHMARK_BASE_CID(7) +#define CID_vespalib_ClockSystem BENCHMARK_BASE_CID(8) +#define CID_vespalib_ClockREALTIME BENCHMARK_BASE_CID(10) +#define CID_vespalib_ClockMONOTONIC BENCHMARK_BASE_CID(11) +#define CID_vespalib_ClockMONOTONIC_RAW BENCHMARK_BASE_CID(12) +#define CID_vespalib_ClockPROCESS_CPUTIME_ID BENCHMARK_BASE_CID(13) +#define CID_vespalib_ClockTHREAD_CPUTIME_ID BENCHMARK_BASE_CID(14) +#define CID_vespalib_CreateVespalibString BENCHMARK_BASE_CID(15) + +#define DECLARE_BENCHMARK(a) DECLARE_IDENTIFIABLE_NS(vespalib, a) +#define IMPLEMENT_BENCHMARK(a, d) IMPLEMENT_IDENTIFIABLE_NS(vespalib, a, d) + +namespace vespalib { + +class Benchmark : public Identifiable +{ +public: + DECLARE_IDENTIFIABLE_ABSTRACT_NS(vespalib, Benchmark); + void run(size_t numRuns, size_t concurrency=1); + static void run(const char * testName, size_t numRuns, size_t concurrency); +private: + virtual size_t onRun() = 0; +}; + +class ParamByReferenceVectorInt : public Benchmark +{ +public: + DECLARE_BENCHMARK(ParamByReferenceVectorInt); +private: + typedef std::vector<int> Vector; + size_t callByReference(const Vector & values) const __attribute__((noinline)); + size_t onRun() override; +}; + +class ParamByValueVectorInt : public Benchmark +{ +public: + DECLARE_BENCHMARK(ParamByValueVectorInt); +private: + typedef std::vector<int> Vector; + size_t callByValue(Vector values) const __attribute__((noinline)); + size_t onRun() override; +}; + +class ParamByReferenceVectorString : public Benchmark +{ +public: + DECLARE_BENCHMARK(ParamByReferenceVectorString); +private: + typedef std::vector<std::string> Vector; + size_t callByReference(const Vector & values) const __attribute__((noinline)); + size_t onRun() override; +}; + +class ParamByValueVectorString : public Benchmark +{ +public: + DECLARE_BENCHMARK(ParamByValueVectorString); +private: + typedef std::vector<std::string> Vector; + size_t callByValue(Vector values) const __attribute__((noinline)); + size_t onRun() override; +}; + +class ReturnByReferenceVectorString : public Benchmark +{ +public: + DECLARE_BENCHMARK(ReturnByReferenceVectorString); +private: + typedef std::vector<std::string> Vector; + const Vector & returnByReference(Vector & values) const __attribute__((noinline)); + size_t onRun() override; +}; + +class ReturnByValueVectorString : public Benchmark +{ +public: + DECLARE_BENCHMARK(ReturnByValueVectorString); +private: + typedef std::vector<std::string> Vector; + Vector returnByValue() const __attribute__((noinline)); + size_t onRun() override; +}; + +class ReturnByValueMultiVectorString : public Benchmark +{ +public: + DECLARE_BENCHMARK(ReturnByValueMultiVectorString); +private: + typedef std::vector<std::string> Vector; + Vector returnByValue() const __attribute__((noinline)); + size_t onRun() override; +}; + +class CreateVespalibString : public Benchmark +{ +public: + DECLARE_BENCHMARK(CreateVespalibString); +private: + size_t onRun() override; +}; + +class ClockSystem : public Benchmark +{ +public: + DECLARE_BENCHMARK(ClockSystem); +private: + size_t onRun() override; +}; + +class ClockREALTIME : public Benchmark +{ +public: + DECLARE_BENCHMARK(ClockREALTIME); +private: + size_t onRun() override; +}; + +class ClockMONOTONIC : public Benchmark +{ +public: + DECLARE_BENCHMARK(ClockMONOTONIC); +private: + size_t onRun() override; +}; + +class ClockMONOTONIC_RAW : public Benchmark +{ +public: + DECLARE_BENCHMARK(ClockMONOTONIC_RAW); + ClockMONOTONIC_RAW(); +private: + size_t onRun() override; +}; + +class ClockPROCESS_CPUTIME_ID : public Benchmark +{ +public: + DECLARE_BENCHMARK(ClockPROCESS_CPUTIME_ID); +private: + size_t onRun() override; +}; + +class ClockTHREAD_CPUTIME_ID : public Benchmark +{ +public: + DECLARE_BENCHMARK(ClockTHREAD_CPUTIME_ID); +private: + size_t onRun() override; +}; + +} |