diff options
author | Håvard Pettersen <havardpe@oath.com> | 2022-01-12 09:16:01 +0000 |
---|---|---|
committer | Håvard Pettersen <havardpe@oath.com> | 2022-01-12 09:41:23 +0000 |
commit | d2ab95dce0a5aa7a2bb8ad44fb33ce66310021d9 (patch) | |
tree | 1674ede0276841d66476bb59e85e8373e38970b5 /vespalib | |
parent | 8c4b988a9eaebf9a7af83f1de0d15a4e6f17374f (diff) |
hide implementation
Diffstat (limited to 'vespalib')
-rw-r--r-- | vespalib/src/tests/cpu_usage/cpu_usage_test.cpp | 22 | ||||
-rw-r--r-- | vespalib/src/vespa/vespalib/util/cpu_usage.cpp | 63 | ||||
-rw-r--r-- | vespalib/src/vespa/vespalib/util/cpu_usage.h | 34 |
3 files changed, 51 insertions, 68 deletions
diff --git a/vespalib/src/tests/cpu_usage/cpu_usage_test.cpp b/vespalib/src/tests/cpu_usage/cpu_usage_test.cpp index d003689b864..98a7bd780a7 100644 --- a/vespalib/src/tests/cpu_usage/cpu_usage_test.cpp +++ b/vespalib/src/tests/cpu_usage/cpu_usage_test.cpp @@ -12,7 +12,6 @@ bool verbose = false; size_t loop_cnt = 10; double budget = 0.25; -using DummySampler = vespalib::cpu_usage::DummyThreadSampler; using Sampler = vespalib::cpu_usage::ThreadSampler; //----------------------------------------------------------------------------- @@ -30,8 +29,7 @@ void be_busy(duration d) { } } -template <typename LIST> -std::vector<duration> sample(const LIST &list) { +std::vector<duration> sample(const std::vector<Sampler*> &list) { std::vector<duration> result; result.reserve(list.size()); for (auto *sampler: list) { @@ -42,8 +40,7 @@ std::vector<duration> sample(const LIST &list) { //----------------------------------------------------------------------------- -template <typename SAMPLER> -void verify_sampling(size_t thread_id, size_t num_threads, std::vector<SAMPLER*> &samplers) { +void verify_sampling(size_t thread_id, size_t num_threads, std::vector<Sampler*> &samplers, bool force_mock) { if (thread_id == 0) { TEST_BARRIER(); // #1 auto t0 = steady_clock::now(); @@ -61,11 +58,10 @@ void verify_sampling(size_t thread_id, size_t num_threads, std::vector<SAMPLER*> EXPECT_GREATER(load[3], load[0]); fprintf(stderr, "loads: { %.2f, %.2f, %.2f, %.2f }\n", load[0], load[1], load[2], load[3]); } else { - SAMPLER sampler; int idx = (thread_id - 1); double target_load = double(thread_id - 1) / (num_threads - 2); - sampler.expected_load(target_load); - samplers[idx] = &sampler; + auto sampler = cpu_usage::create_thread_sampler(force_mock, target_load); + samplers[idx] = sampler.get(); TEST_BARRIER(); // #1 TEST_BARRIER(); // #2 for (size_t i = 0; i < loop_cnt; ++i) { @@ -78,18 +74,18 @@ void verify_sampling(size_t thread_id, size_t num_threads, std::vector<SAMPLER*> //----------------------------------------------------------------------------- -TEST_MT_F("require that dummy thread-based CPU usage sampling with known expected load works", 5, std::vector<DummySampler*>(4, nullptr)) { - TEST_DO(verify_sampling(thread_id, num_threads, f1)); +TEST_MT_F("require that dummy thread-based CPU usage sampling with known expected load works", 5, std::vector<Sampler*>(4, nullptr)) { + TEST_DO(verify_sampling(thread_id, num_threads, f1, true)); } TEST_MT_F("require that external thread-based CPU usage sampling works", 5, std::vector<Sampler*>(4, nullptr)) { - TEST_DO(verify_sampling(thread_id, num_threads, f1)); + TEST_DO(verify_sampling(thread_id, num_threads, f1, false)); } TEST("measure thread CPU clock overhead") { - Sampler sampler; + auto sampler = cpu_usage::create_thread_sampler(); duration d; - double min_time_us = BenchmarkTimer::benchmark([&d, &sampler]() noexcept { d = sampler.sample(); }, budget) * 1000000.0; + 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); } diff --git a/vespalib/src/vespa/vespalib/util/cpu_usage.cpp b/vespalib/src/vespa/vespalib/util/cpu_usage.cpp index 1c126cb7884..4eee0a63870 100644 --- a/vespalib/src/vespa/vespalib/util/cpu_usage.cpp +++ b/vespalib/src/vespa/vespalib/util/cpu_usage.cpp @@ -2,45 +2,54 @@ #include "cpu_usage.h" #include "require.h" +#include <pthread.h> namespace vespalib { namespace cpu_usage { -DummyThreadSampler::DummyThreadSampler() - : _start(steady_clock::now()), - _load(0.16) -{ -} +namespace { -void -DummyThreadSampler::expected_load(double load) { - _load = load; -} - -duration -DummyThreadSampler::sample() const -{ - return from_s(to_s(steady_clock::now() - _start) * _load); -} +class DummyThreadSampler : public ThreadSampler { +private: + steady_time _start; + double _load; +public: + DummyThreadSampler(double load) : _start(steady_clock::now()), _load(load) {} + duration sample() const override { + return from_s(to_s(steady_clock::now() - _start) * _load); + } +}; #ifdef __linux__ -ThreadSampler::ThreadSampler() - : _my_clock() -{ - REQUIRE_EQ(pthread_getcpuclockid(pthread_self(), &_my_clock), 0); -} +class LinuxThreadSampler : public ThreadSampler { +private: + clockid_t _my_clock; +public: + LinuxThreadSampler() : _my_clock() { + REQUIRE_EQ(pthread_getcpuclockid(pthread_self(), &_my_clock), 0); + } + duration sample() const override { + timespec ts; + REQUIRE_EQ(clock_gettime(_my_clock, &ts), 0); + return from_timespec(ts); + } +}; -duration -ThreadSampler::sample() const -{ - timespec ts; - REQUIRE_EQ(clock_gettime(_my_clock, &ts), 0); - return from_timespec(ts); -} +#endif + +} // <unnamed> +ThreadSampler::UP create_thread_sampler(bool force_mock_impl, double expected_load) { + if (force_mock_impl) { + return std::make_unique<DummyThreadSampler>(expected_load); + } +#ifdef __linux__ + return std::make_unique<LinuxThreadSampler>(); #endif + return std::make_unique<DummyThreadSampler>(expected_load); +} } // cpu_usage diff --git a/vespalib/src/vespa/vespalib/util/cpu_usage.h b/vespalib/src/vespa/vespalib/util/cpu_usage.h index 03a438ef6aa..09509a984b5 100644 --- a/vespalib/src/vespa/vespalib/util/cpu_usage.h +++ b/vespalib/src/vespa/vespalib/util/cpu_usage.h @@ -1,46 +1,24 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -#include <pthread.h> #include <vespa/vespalib/util/time.h> +#include <memory> namespace vespalib { namespace cpu_usage { -// do not use this directly (use ThreadSampler) -class DummyThreadSampler { -private: - steady_time _start; - double _load; -public: - DummyThreadSampler(); - void expected_load(double load); - duration sample() const; -}; - -#ifdef __linux__ - /** * Samples the total CPU usage of the thread that created it. Note * that this must not be used after thread termination. Enables * sampling the CPU usage of a thread from outside the thread. - * - * uses: pthread_self, pthread_getcpuclockid, clock_gettime **/ -class ThreadSampler { -private: - clockid_t _my_clock; -public: - ThreadSampler(); - constexpr void expected_load(double) noexcept {} - duration sample() const; +struct ThreadSampler { + using UP = std::unique_ptr<ThreadSampler>; + virtual duration sample() const = 0; + virtual ~ThreadSampler() {} }; -#else - -using ThreadSampler = DummyThreadSampler; - -#endif +ThreadSampler::UP create_thread_sampler(bool force_mock_impl = false, double expected_load = 0.16); } // cpu_usage |