From c848a90094ea1e7e2426e8458ce924a70879bb5c Mon Sep 17 00:00:00 2001 From: Travis Downs Date: Fri, 22 Nov 2024 11:58:23 -0300 Subject: [PATCH] wip: metrics_perf bench --- tests/perf/CMakeLists.txt | 3 + tests/perf/metrics_perf.cc | 147 +++++++++++++++++++++++++++++++++++++ 2 files changed, 150 insertions(+) create mode 100644 tests/perf/metrics_perf.cc diff --git a/tests/perf/CMakeLists.txt b/tests/perf/CMakeLists.txt index fa715c3598..a851a01612 100644 --- a/tests/perf/CMakeLists.txt +++ b/tests/perf/CMakeLists.txt @@ -92,3 +92,6 @@ seastar_add_test (container seastar_add_test (http_client SOURCES http_client_perf.cc linux_perf_event.cc NO_SEASTAR_PERF_TESTING_LIBRARY) + +seastar_add_test (metrics + SOURCES metrics_perf.cc) diff --git a/tests/perf/metrics_perf.cc b/tests/perf/metrics_perf.cc new file mode 100644 index 0000000000..ecadcd2a94 --- /dev/null +++ b/tests/perf/metrics_perf.cc @@ -0,0 +1,147 @@ +/* + * This file is open source software, licensed to you under the terms + * of the Apache License, Version 2.0 (the "License"). See the NOTICE file + * distributed with this work for additional information regarding copyright + * ownership. You may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "seastar/core/fstream.hh" +#include "seastar/core/iostream.hh" +#include "seastar/core/metrics.hh" +#include "seastar/core/metrics_registration.hh" +#include "seastar/core/prometheus.hh" +#include "seastar/testing/perf_tests.hh" +#include + + +#include + +// just records the size of everything written +struct counting_data_sink_impl : public data_sink_impl { + counting_data_sink_impl(size_t buf_size) : buf_size{buf_size} {} + + virtual future<> put(net::packet data) override { + abort(); + return make_ready_future<>(); + } + + virtual future<> put(temporary_buffer buf) override { + written += buf.size(); + return make_ready_future<>(); + } + + virtual future<> flush() override { + return make_ready_future<>(); + } + + virtual future<> close() override { + return make_ready_future<>(); + } + + virtual size_t buffer_size() const noexcept override { + return buf_size; + } + + size_t written = 0; + size_t buf_size; +}; + +class counting_data_sink : public data_sink { +public: + counting_data_sink() + : data_sink(std::make_unique(32000)) {} +}; + + +namespace seastar::prometheus::details { + +struct metrics_perf_fixture { + seastar::future run_metrics_bench(size_t group_count, size_t families_per_group, size_t series_per_family) { + using namespace seastar; + using namespace seastar::metrics; + + metric_groups perf_metrics; + + const size_t series_count = group_count * families_per_group * series_per_family; + + constexpr size_t name_length = 50; + + sstring name_template = (sstring("gauge") + sstring(name_length, '_')).substr(0, name_length - 3) + "{}"; + std::string_view name_template_sv = name_template; + + auto label_template = fmt::runtime("label_value_{}"); + + label label_0{"some-long-label-name-this-happens-in-real-life"}, label_1{"short"}; + + for (auto group_id : boost::irange(group_count)) { + std::vector defs; + for (auto family_id : boost::irange(families_per_group)) { + auto name = fmt::format(fmt::runtime(name_template_sv), family_id); + auto desc = fmt::format(fmt::runtime(name_template_sv), family_id); + + for (auto label_id : boost::irange(series_per_family)) { + auto label0 = label_0(fmt::format(label_template, label_id)); + auto label1 = label_0(fmt::format(label_template, label_id)); + defs.emplace_back( + make_counter(name, description(name), {label0, label1}, [] { return 0.0; })); + } + } + perf_metrics.add_group(fmt::format("group-{}", group_id), defs); + } + + prometheus::config config{}; + + using access = prometheus::details::test_access; + + + auto tf = co_await seastar::make_tmp_file(); + // fmt::print("File at: {}\n", tf.get_path().native()); + + + constexpr int iterations = 1; + + for (auto _ : boost::irange(iterations)) { + // auto out_file = tf.get_file().dup().to_file(); + // output_stream out = co_await make_file_output_stream(out_file, 32 * 1024); + output_stream out{counting_data_sink{}}; + perf_tests::start_measuring_time(); + co_await access{}.write_body(config, "", false, true, false, [](auto mi){ return true; }, std::move(out)); + perf_tests::stop_measuring_time(); + } + + co_await tf.close(); + co_await tf.remove(); + + co_return series_count * iterations; + } + +}; + +PERF_TEST_CN(metrics_perf_fixture, test_large_families) { + // relatively few familities, but many series in each, stresses + // "per series" work + co_return co_await run_metrics_bench(1, 1, 10000); +} + +PERF_TEST_CN(metrics_perf_fixture, test_many_families) { + // many families, each with only 1 series, stresses "per family" + // work + co_return co_await run_metrics_bench(1, 10000, 1); +} + +PERF_TEST_CN(metrics_perf_fixture, test_middle_ground) { + co_return co_await run_metrics_bench(1, 1000, 10); +} + +}