]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
tests(dnsdist): Add micro benchmarking
authorPieter Lexis <pieter.lexis@powerdns.com>
Mon, 20 Oct 2025 12:12:28 +0000 (14:12 +0200)
committerPieter Lexis <pieter.lexis@powerdns.com>
Wed, 7 Jan 2026 12:16:20 +0000 (13:16 +0100)
pdns/dnsdistdist/bench-dnsdist-opentelemetry_cc.cc [new file with mode: 0644]
pdns/dnsdistdist/benchmarkrunner.cc [new file with mode: 0644]
pdns/dnsdistdist/meson.build
pdns/dnsdistdist/meson/catch2/meson.build [new file with mode: 0644]
pdns/dnsdistdist/meson_options.txt

diff --git a/pdns/dnsdistdist/bench-dnsdist-opentelemetry_cc.cc b/pdns/dnsdistdist/bench-dnsdist-opentelemetry_cc.cc
new file mode 100644 (file)
index 0000000..679c9ae
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * This file is part of PowerDNS or dnsdist.
+ * Copyright -- PowerDNS.COM B.V. and its contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * In addition, for the avoidance of any doubt, permission is granted to
+ * link this program with OpenSSL and to (re)distribute the binaries
+ * produced as the result of such linking.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef DISABLE_PROTOBUF
+#define CATCH_CONFIG_NO_MAIN
+#include <catch2/catch_test_macros.hpp>
+#include <catch2/benchmark/catch_benchmark.hpp>
+#include <string>
+
+#include "dnsdist-opentelemetry.hh"
+#include "protozero-trace.hh"
+
+TEST_CASE("OpenTelemetry-base") {
+  BENCHMARK("pdns::trace::dnsdist::Tracer::getTracer") {
+    return pdns::trace::dnsdist::Tracer::getTracer();
+  };
+
+  auto tracer = pdns::trace::dnsdist::Tracer::getTracer();
+  auto spanID = pdns::trace::SpanID::getRandomSpanID();
+
+  BENCHMARK("pdns::trace::dnsdist::Tracer::getCloser") {
+    return tracer->getCloser(spanID);
+  };
+
+  BENCHMARK("pdns::trace::dnsdist::Tracer::openSpan") {
+    return tracer->openSpan("foo");
+  };
+}
+
+TEST_CASE("OpenTelemetry-spaninfo") {
+  auto tracer = pdns::trace::dnsdist::Tracer::getTracer();
+  // Ensures span attributes are actually stored
+  tracer->activate();
+  auto rootSpanID = tracer->openSpan("mySpan").getSpanID();
+  auto stringvalue = pdns::trace::AnyValue{"hello"};
+  auto intvalue = pdns::trace::AnyValue{43854};
+
+  BENCHMARK("dnsdist::trace::Tracer::setSpanAttribute-string one span") {
+    tracer->setSpanAttribute(rootSpanID, "key", stringvalue);
+  };
+
+  BENCHMARK("dnsdist::trace::Tracer::setSpanAttribute-int one span") {
+    tracer->setSpanAttribute(rootSpanID, "key", intvalue);
+  };
+
+  auto spanID = rootSpanID;
+  for (auto i=0; i < 40; i++) {
+    spanID = tracer->openSpan("fooSpan" + std::to_string(i), spanID).getSpanID();
+  }
+
+  BENCHMARK("dnsdist::trace::Tracer::setSpanAttribute-string 42 spans, first") {
+    tracer->setSpanAttribute(rootSpanID, "key", stringvalue);
+  };
+
+  BENCHMARK("dnsdist::trace::Tracer::setSpanAttribute-int 42 spans, first") {
+    tracer->setSpanAttribute(rootSpanID, "key", intvalue);
+  };
+
+  BENCHMARK("dnsdist::trace::Tracer::setSpanAttribute-string 42 spans, last") {
+    tracer->setSpanAttribute(spanID, "key", stringvalue);
+  };
+
+  BENCHMARK("dnsdist::trace::Tracer::setSpanAttribute-int 42 spans, last") {
+    tracer->setSpanAttribute(spanID, "key", intvalue);
+  };
+
+}
+
+TEST_CASE("OpenTelemetry-getLastSpanID") {
+  auto tracer = pdns::trace::dnsdist::Tracer::getTracer();
+  pdns::trace::dnsdist::Tracer::Closer closer;
+  for (auto i=0; i < 40; i++) {
+    closer = tracer->openSpan("foo" + std::to_string(i));
+  }
+
+  BENCHMARK("getLastSpanID") {
+    return tracer->getLastSpanID();
+  };
+
+  BENCHMARK("getRootSpanID") {
+    return tracer->getRootSpanID();
+  };
+
+  BENCHMARK("getLastSpanIDForName-first") {
+    return tracer->getLastSpanIDForName("foo0");
+  };
+
+  BENCHMARK("getLastSpanIDForName-middle") {
+    return tracer->getLastSpanIDForName("foo20");
+  };
+
+  BENCHMARK("getLastSpanIDForName-does-not-exist") {
+    return tracer->getLastSpanIDForName("doesnotexist");
+  };
+}
+
+TEST_CASE("OpenTelemetry-getTracesData") {
+  auto tracer = pdns::trace::dnsdist::Tracer::getTracer();
+
+  BENCHMARK("empty Tracer") {
+    return tracer->getTracesData();
+  };
+
+  for (auto i=0; i < 40; i++) {
+    tracer->openSpan("foo" + std::to_string(i));
+  }
+
+  BENCHMARK("Tracer with 41 pre-activation spans") {
+    return tracer->getTracesData();
+  };
+
+  tracer = pdns::trace::dnsdist::Tracer::getTracer();
+  tracer->activate();
+  for (auto i=0; i < 40; i++) {
+    tracer->openSpan("foo" + std::to_string(i));
+  }
+
+  BENCHMARK("Tracer with 41 post-activation spans") {
+    return tracer->getTracesData();
+  };
+
+  tracer = pdns::trace::dnsdist::Tracer::getTracer();
+  for (auto i=0; i < 40; i++) {
+    tracer->openSpan("foo" + std::to_string(i));
+  }
+  tracer->activate();
+  for (auto i=0; i < 40; i++) {
+    tracer->openSpan("foo" + std::to_string(i));
+  }
+
+  BENCHMARK("Tracer with 41 pre-activation spans and 41 post-activation spans") {
+    return tracer->getTracesData();
+  };
+}
+#endif
diff --git a/pdns/dnsdistdist/benchmarkrunner.cc b/pdns/dnsdistdist/benchmarkrunner.cc
new file mode 100644 (file)
index 0000000..6d1bc34
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * This file is part of PowerDNS or dnsdist.
+ * Copyright -- PowerDNS.COM B.V. and its contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * In addition, for the avoidance of any doubt, permission is granted to
+ * link this program with OpenSSL and to (re)distribute the binaries
+ * produced as the result of such linking.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#define CATCH_CONFIG_MAIN
+#include <catch2/catch_config.hpp>
index a72297c0d7579268faff0031f07114de6d75bcfc..af0182b83c0f6610034a8d32111aa44ed5de832a 100644 (file)
@@ -85,6 +85,7 @@ subdir('meson' / 'doh2')                    # DNS over HTTP/2
 subdir('meson' / 'doq')                     # DNS over QUIC
 subdir('meson' / 'doh3')                    # DNS over HTTP/3
 subdir('meson' / 'yaml-configuration')      # YAML configuration
+subdir('meson' / 'catch2')                  # Microbenchmark
 
 common_sources = []
 
@@ -593,6 +594,36 @@ if get_option('unit-tests')
   }
 endif
 
+benchmark_sources = []
+benchmark_sources += files(
+  src_dir / 'bench-dnsdist-opentelemetry_cc.cc'
+)
+
+if get_option('benchmark')
+  libdnsdist_benchmark = declare_dependency(
+    link_whole: static_library(
+      'dnsdist-benchmark',
+      config_h,
+      benchmark_sources,
+      dependencies: [
+          dep_catch2,
+          dep_protozero,
+      ],
+    )
+  )
+
+  tools += {
+    'benchmarkrunner' : {
+      'main': [
+        src_dir / 'benchmarkrunner.cc',
+      ],
+        'deps-extra': [
+          libdnsdist_benchmark,
+      ],
+    }
+  }
+endif
+
 man_pages = []
 foreach tool, info: tools
   var_name = tool.underscorify()
@@ -632,6 +663,10 @@ if get_option('unit-tests')
   test('testrunner', testrunner)
 endif
 
+if get_option('benchmark')
+  benchmark('benchmarkrunner', benchmarkrunner)
+endif
+
 # Man-pages.
 python_venv = py.find_installation('python3', modules: 'venv', required: false)
 
diff --git a/pdns/dnsdistdist/meson/catch2/meson.build b/pdns/dnsdistdist/meson/catch2/meson.build
new file mode 100644 (file)
index 0000000..13d02ad
--- /dev/null
@@ -0,0 +1,5 @@
+dep_catch2 = dependency('', required: false)
+if get_option('benchmark')
+  dep_catch2 = dependency('catch2-with-main', version: '>=3',  required: true)
+  summary('Catch2', dep_catch2.found(), bool_yn: true, section: 'Configuration')
+endif
index 3f506142c50c22c6ed8fefaf93022db9774d3c38..e66d1d4091f1ed2cbf09e0f7db4d6fe0bc79e707 100644 (file)
@@ -41,3 +41,4 @@ option('fuzzer_ldflags', type: 'string', value: '', description: 'Linker flags u
 option('yaml', type: 'feature', value: 'disabled', description: 'Enable YAML configuration')
 option('man-pages', type: 'boolean', value: true, description: 'Generate man pages')
 option('clang-coverage-format', type: 'boolean', value: false, description: 'Whether to generate coverage data in clang format')
+option('benchmark', type: 'boolean', value: false, description: 'Whether to run microbenchmarks')