diff options
Diffstat (limited to 'vespalib/src/tests/cpu_usage/cpu_usage_test.cpp')
-rw-r--r-- | vespalib/src/tests/cpu_usage/cpu_usage_test.cpp | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/vespalib/src/tests/cpu_usage/cpu_usage_test.cpp b/vespalib/src/tests/cpu_usage/cpu_usage_test.cpp new file mode 100644 index 00000000000..c8835d82cd8 --- /dev/null +++ b/vespalib/src/tests/cpu_usage/cpu_usage_test.cpp @@ -0,0 +1,94 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#include <vespa/vespalib/util/cpu_usage.h> +#include <vespa/vespalib/util/benchmark_timer.h> +#include <vespa/vespalib/testkit/test_kit.h> + +#include <thread> + +using namespace vespalib; + +bool verbose = false; +size_t loop_cnt = 10; +double budget = 0.25; + +using Sampler = vespalib::cpu_usage::ThreadSampler; + +//----------------------------------------------------------------------------- + +void be_busy(duration d) { + if (d > 0ms) { + volatile int tmp = 123; + auto t0 = steady_clock::now(); + while ((steady_clock::now() - t0) < d) { + for (int i = 0; i < 1000; ++i) { + tmp = (tmp + i); + tmp = (tmp - i); + } + } + } +} + +std::vector<duration> sample(const std::vector<Sampler*> &list) { + std::vector<duration> result; + result.reserve(list.size()); + for (Sampler *sampler: list) { + result.push_back(sampler->sample()); + } + return result; +} + +//----------------------------------------------------------------------------- + +TEST_MT_F("require that external thread-based CPU usage sampling works", 5, std::vector<Sampler*>(4, nullptr)) { + if (thread_id == 0) { + TEST_BARRIER(); // #1 + auto t0 = steady_clock::now(); + std::vector<duration> pre_usage = sample(f1); + TEST_BARRIER(); // #2 + TEST_BARRIER(); // #3 + auto t1 = steady_clock::now(); + std::vector<duration> post_usage = sample(f1); + TEST_BARRIER(); // #4 + double wall = to_s(t1 - t0); + std::vector<double> load(4, 0.0); + for (size_t i = 0; i < 4; ++i) { + load[i] = to_s(post_usage[i] - pre_usage[i]) / wall; + } + EXPECT_GREATER(load[3], load[0]); + fprintf(stderr, "loads: { %.2f, %.2f, %.2f, %.2f }\n", load[0], load[1], load[2], load[3]); + } else { + int idx = (thread_id - 1); + Sampler sampler; + f1[idx] = &sampler; + TEST_BARRIER(); // #1 + TEST_BARRIER(); // #2 + for (size_t i = 0; i < loop_cnt; ++i) { + be_busy(std::chrono::milliseconds(idx)); + } + TEST_BARRIER(); // #3 + TEST_BARRIER(); // #4 + } +} + +//----------------------------------------------------------------------------- + +TEST("measure thread CPU clock overhead") { + Sampler sampler; + duration d; + double min_time_us = BenchmarkTimer::benchmark([&d, &sampler]() noexcept { d = sampler.sample(); }, budget) * 1000000.0; + fprintf(stderr, "approx overhead per sample (thread CPU clock): %f us\n", min_time_us); +} + +//----------------------------------------------------------------------------- + +int main(int argc, char **argv) { + TEST_MASTER.init(__FILE__); + if ((argc == 2) && (argv[1] == std::string("verbose"))) { + verbose = true; + loop_cnt = 1000; + budget = 5.0; + } + TEST_RUN_ALL(); + return (TEST_MASTER.fini() ? 0 : 1); +} |