summaryrefslogtreecommitdiffstats
path: root/vespalib/src/tests/benchmark
diff options
context:
space:
mode:
authorHenning Baldersheim <balder@yahoo-inc.com>2022-05-19 21:57:59 +0000
committerHenning Baldersheim <balder@yahoo-inc.com>2022-05-20 12:38:48 +0000
commit64500ab17deb86b394edc81f4ad42b5a2c43fe30 (patch)
tree64334ba1513b697dacd5068981a8ee5b7ad92f3b /vespalib/src/tests/benchmark
parentcfa6ec5cdbd1cf39558d3f85101de05230d6c225 (diff)
Fold staging_vespalib into vespalib
Diffstat (limited to 'vespalib/src/tests/benchmark')
-rw-r--r--vespalib/src/tests/benchmark/.gitignore4
-rw-r--r--vespalib/src/tests/benchmark/CMakeLists.txt12
-rw-r--r--vespalib/src/tests/benchmark/benchmark.cpp30
-rwxr-xr-xvespalib/src/tests/benchmark/benchmark_test.sh21
-rw-r--r--vespalib/src/tests/benchmark/testbase.cpp279
-rw-r--r--vespalib/src/tests/benchmark/testbase.h168
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;
+};
+
+}