This is an automated email from the ASF dual-hosted git repository.
cmcfarlen pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/master by this push:
new 37561f25b4 build tests for hostdb. Add new benchmark for hostdb
(#11760)
37561f25b4 is described below
commit 37561f25b4080447259f9eec2f6b6e37e3013f11
Author: Chris McFarlen <[email protected]>
AuthorDate: Thu Sep 12 09:24:44 2024 -0500
build tests for hostdb. Add new benchmark for hostdb (#11760)
* build tests for hostdb. Add new benchmark for hostdb
* provide minimal latch impl if needed
Fix build
* cleanup
* Remove unused hostdb test files
* PR feedback
---------
Co-authored-by: Chris McFarlen <[email protected]>
---
src/iocore/hostdb/CMakeLists.txt | 23 +++
src/iocore/hostdb/benchmark_HostDB.cc | 308 ++++++++++++++++++++++++++++++++
src/iocore/hostdb/test_HostFile.cc | 22 +++
src/iocore/hostdb/test_I_HostDB.cc | 50 ------
src/iocore/hostdb/test_P_HostDB.cc | 82 ---------
src/iocore/hostdb/test_RefCountCache.cc | 4 +-
6 files changed, 355 insertions(+), 134 deletions(-)
diff --git a/src/iocore/hostdb/CMakeLists.txt b/src/iocore/hostdb/CMakeLists.txt
index 40a0603111..9da43196ee 100644
--- a/src/iocore/hostdb/CMakeLists.txt
+++ b/src/iocore/hostdb/CMakeLists.txt
@@ -21,3 +21,26 @@ add_library(ts::inkhostdb ALIAS inkhostdb)
target_link_libraries(inkhostdb PUBLIC ts::inkdns ts::inkevent ts::tscore)
clang_tidy_check(inkhostdb)
+
+if(BUILD_TESTING)
+ add_executable(benchmark_HostDB benchmark_HostDB.cc)
+ target_link_libraries(
+ benchmark_HostDB
+ PRIVATE ts::tscore
+ ts::tsutil
+ ts::inkevent
+ ts::http
+ ts::http_remap
+ ts::inkcache
+ ts::inkhostdb
+ )
+
+ add_executable(test_HostFile test_HostFile.cc HostFile.cc HostDBInfo.cc)
+ target_link_libraries(test_HostFile PRIVATE ts::tscore ts::tsutil
ts::inkevent catch2::catch2)
+ add_test(NAME test_hostdb_HostFile COMMAND $<TARGET_FILE:test_HostFile>)
+
+ add_executable(test_RefCountCache test_RefCountCache.cc)
+ target_link_libraries(test_RefCountCache PRIVATE ts::tscore ts::tsutil
ts::inkevent catch2::catch2)
+ add_test(NAME test_hostdb_RefCountCache COMMAND
$<TARGET_FILE:test_RefCountCache>)
+
+endif()
diff --git a/src/iocore/hostdb/benchmark_HostDB.cc
b/src/iocore/hostdb/benchmark_HostDB.cc
new file mode 100644
index 0000000000..8b407f9411
--- /dev/null
+++ b/src/iocore/hostdb/benchmark_HostDB.cc
@@ -0,0 +1,308 @@
+/** @file
+
+ Test HostFile
+
+ @section license License
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); 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 "iocore/dns/DNSProcessor.h"
+#include "iocore/eventsystem/Continuation.h"
+#include "iocore/eventsystem/EventProcessor.h"
+#include "iocore/eventsystem/EventSystem.h"
+#include "iocore/eventsystem/Lock.h"
+#include "iocore/net/NetProcessor.h"
+#include "records/RecordsConfig.h"
+#include "swoc/swoc_file.h"
+#include "tscore/DiagsTypes.h"
+#include "tscore/Layout.h"
+#include "iocore/eventsystem/RecProcess.h"
+#include "iocore/hostdb/HostDBProcessor.h"
+#include "tscore/TSSystemState.h"
+#include "tscore/Version.h"
+#include "tscore/ink_hrtime.h"
+#include "tscore/ink_hw.h"
+#include "tsutil/DbgCtl.h"
+#include <algorithm>
+#include <functional>
+
+#include "iocore/hostdb/HostDB.h"
+
+#include <random>
+#include <fstream>
+
+#if __has_include(<latch>)
+#include <latch>
+using latch = std::latch;
+#else
+struct latch {
+ int count;
+ std::mutex m;
+ std::condition_variable cv;
+
+ latch(int count) : count(count) {}
+
+ void
+ wait()
+ {
+ std::unique_lock lock{m};
+ cv.wait(lock, [this] { return count == 0; });
+ }
+
+ void
+ count_down()
+ {
+ std::unique_lock lock{m};
+ if (0 == --count) {
+ cv.notify_all();
+ }
+ }
+};
+#endif
+
+namespace
+{
+
+DbgCtl dbg_ctl_hostdb_test{"hostdb_test"};
+HostDBProcessor hdb;
+
+} // end anonymous namespace
+
+std::string
+temp_prefix()
+{
+ char buffer[PATH_MAX];
+ std::error_code err;
+ const char *tmpdir = getenv("TMPDIR");
+ if (tmpdir == nullptr) {
+ tmpdir = "/tmp";
+ }
+ snprintf(buffer, sizeof(buffer), "%s/cachetest.XXXXXX", tmpdir);
+ auto prefix = swoc::file::path(mkdtemp(buffer));
+ bool result = swoc::file::create_directories(prefix / "var" /
"trafficserver", err, 0755);
+ if (!result) {
+ Dbg(dbg_ctl_hostdb_test, "Failed to create directories for test: %s(%s)",
prefix.c_str(), err.message().c_str());
+ }
+ ink_assert(result);
+
+ return prefix.string();
+}
+
+void
+init_ts(std::string_view name, int debug_on = 0)
+{
+ DiagsPtr::set(new Diags(name, "", "", new BaseLogFile("stderr")));
+ swoc::file::path prefix = temp_prefix();
+
+ diags()->activate_taglist("dns|hostdb", DiagsTagType_Debug);
+ diags()->config.enabled(DiagsTagType_Debug, debug_on);
+ diags()->show_location = SHOW_LOCATION_DEBUG;
+
+ Layout::create(prefix.view());
+ RecProcessInit(diags());
+ LibRecordsConfigInit();
+ ink_event_system_init(ts::ModuleVersion(1, 0, ts::ModuleVersion::PRIVATE));
+ ink_net_init(ts::ModuleVersion(1, 0, ts::ModuleVersion::PRIVATE));
+ ink_hostdb_init(HOSTDB_MODULE_PUBLIC_VERSION);
+ ink_dns_init(HOSTDB_MODULE_PUBLIC_VERSION);
+
+ netProcessor.init();
+
+ const int nproc = ink_number_of_processors();
+ eventProcessor.start(nproc);
+ dnsProcessor.start(0, 1024 * 1024);
+
+ hdb.start();
+
+ EThread *thread = new EThread();
+ thread->set_specific();
+ init_buffer_allocators(0);
+}
+
+struct StartDNS : Continuation {
+ struct Result {
+ std::chrono::duration<float> d;
+ std::string hostname;
+ std::string ip;
+ bool immediate;
+ };
+ using HostList = std::vector<std::string>;
+ using ResultList = std::vector<Result>;
+ using Clock = std::chrono::high_resolution_clock;
+ using ms = std::chrono::milliseconds;
+
+ HostList hostlist;
+ int id;
+ latch &done_latch;
+ HostList::iterator it;
+ ResultList results;
+ Clock::time_point start_time;
+ bool is_callback;
+
+ StartDNS(const std::vector<std::string> &hlist, int id, latch &l)
+ : Continuation(new_ProxyMutex()), hostlist(hlist), id(id), done_latch(l)
+ {
+ std::random_device rd;
+ std::mt19937 gen{rd()};
+
+ std::shuffle(hostlist.begin(), hostlist.end(), gen);
+ it = hostlist.begin();
+
+ SET_HANDLER(&StartDNS::start_dns);
+ }
+
+ std::string
+ ip(HostDBRecord *r)
+ {
+ char buff[256];
+ r->rr_info()[0].data.ip.toString(buff, sizeof(buff));
+ return buff;
+ }
+
+ void
+ handle_hostdb(HostDBRecord *r)
+ {
+ auto now = Clock::now();
+ results.push_back(Result{
+ now - start_time,
+ r->name(),
+ ip(r),
+ !is_callback,
+ });
+ }
+
+ void
+ print_results()
+ {
+ for (auto &res : results) {
+ std::printf("[%02d] %32s: %-20s %f (%s)\n", id, res.hostname.c_str(),
res.ip.c_str(), res.d.count(),
+ res.immediate ? "true" : "false");
+ }
+ }
+
+ int
+ start_dns(int e, void *ep)
+ {
+ switch (e) {
+ case EVENT_HOST_DB_LOOKUP:
+ is_callback = true;
+ handle_hostdb(reinterpret_cast<HostDBRecord *>(ep));
+ [[fallthrough]];
+ default:
+ Dbg(dbg_ctl_hostdb_test, "start_dns event %d", e);
+ do {
+ if (it == hostlist.end()) {
+ done_latch.count_down();
+ return 0;
+ }
+ start_time = Clock::now();
+ is_callback = false;
+ } while (hdb.getbyname_imm(this,
static_cast<cb_process_result_pfn>(&StartDNS::handle_hostdb), (it++)->c_str(),
0) ==
+ ACTION_RESULT_DONE);
+ break;
+ }
+ return 0;
+ }
+};
+
+StartDNS::HostList
+lines(const std::string &fname)
+{
+ std::ifstream in(fname);
+ std::string line;
+ StartDNS::HostList result;
+
+ if (in.is_open()) {
+ while (std::getline(in, line)) {
+ result.push_back(line);
+ }
+ in.close();
+ } else {
+ printf("Failed to open file %s\n", fname.c_str());
+ }
+
+ return result;
+}
+
+int
+main(int argc, char **argv)
+{
+ StartDNS::HostList hosts;
+ if (argc > 1) {
+ hosts = lines(argv[1]);
+ } else {
+ hosts = {
+ "www.yahoo.com", "developer.apple.com", "www.google.com",
"www.apple.com",
+ "sports.yahoo.com", "finance.yahoo.com", "www.github.com",
+ };
+ }
+ int dbg = 0;
+ if (argc > 2) {
+ dbg = 1;
+ }
+
+ init_ts("hostdb_test", dbg);
+
+ auto threads = eventProcessor.active_group_threads(ET_CALL);
+ int count = threads.end() - threads.begin();
+
+ latch l{count};
+ std::vector<StartDNS *> tests;
+
+ for (auto &t : eventProcessor.active_group_threads(ET_CALL)) {
+ StartDNS *startDns = new StartDNS{hosts, t->id, l};
+ t->schedule_imm(startDns);
+ tests.push_back(startDns);
+ }
+
+ l.wait();
+
+ int results_count{};
+ int dns_count{};
+ std::chrono::duration<float> total_duration{};
+ std::chrono::duration<float> min_d = std::chrono::duration<float>::max();
+ std::chrono::duration<float> max_d{};
+ std::chrono::duration<float> min_i = std::chrono::duration<float>::max();
+ std::chrono::duration<float> max_i{};
+
+ for (auto *test : tests) {
+ test->print_results();
+ results_count += test->results.size();
+ for (const auto &r : test->results) {
+ total_duration += r.d;
+ if (!r.immediate) {
+ dns_count += 1;
+ min_d = std::min(min_d, r.d);
+ max_d = std::max(max_d, r.d);
+ } else {
+ min_i = std::min(min_i, r.d);
+ max_i = std::max(max_i, r.d);
+ }
+ }
+ delete test;
+ }
+
+ printf("Hosts: %zu lookup count: %d thread count: %d\n", hosts.size(),
dns_count, count);
+ printf("dns min/max: %2.6f/%2.6f\n", min_d.count(), max_d.count());
+ printf("imm min/max: %2.6f/%2.6f\n", min_i.count(), max_i.count());
+ printf("Total results: %d average lookup %f\n", results_count,
total_duration.count() / results_count);
+ hdb.shutdown();
+}
+
+class HttpSessionAccept;
+HttpSessionAccept *plugin_http_accept = nullptr;
diff --git a/src/iocore/hostdb/test_HostFile.cc
b/src/iocore/hostdb/test_HostFile.cc
index 031ce61a3a..aa3a27ecd7 100644
--- a/src/iocore/hostdb/test_HostFile.cc
+++ b/src/iocore/hostdb/test_HostFile.cc
@@ -30,6 +30,9 @@
#include "iocore/hostdb/HostFile.h"
#include "P_HostDBProcessor.h"
+#include "iocore/eventsystem/EventSystem.h"
+#include "tscore/Layout.h"
+#include "iocore/utils/diags.i"
using namespace std::literals;
@@ -41,6 +44,25 @@ DbgCtl dbg_ctl_hostdb{"hostdb"};
const std::string_view hosts_data = "127.0.0.1 localhost\n::1
localhost\n1.2.3.4 host1\n4.3.2.1 host2 host3\n";
} // end anonymous namespace
+struct EventProcessorListener : Catch::TestEventListenerBase {
+ using TestEventListenerBase::TestEventListenerBase;
+
+ void
+ testRunStarting(Catch::TestRunInfo const & /* testRunInfo ATS_UNUSED */)
override
+ {
+ Layout::create();
+ init_diags("", nullptr);
+ RecProcessInit();
+
+ ink_event_system_init(EVENT_SYSTEM_MODULE_PUBLIC_VERSION);
+ eventProcessor.start(2);
+
+ EThread *main_thread = new EThread;
+ main_thread->set_specific();
+ }
+};
+
+CATCH_REGISTER_LISTENER(EventProcessorListener);
void
spit(const swoc::file::path &p, std::string_view data)
diff --git a/src/iocore/hostdb/test_I_HostDB.cc
b/src/iocore/hostdb/test_I_HostDB.cc
deleted file mode 100644
index e56fdea3cf..0000000000
--- a/src/iocore/hostdb/test_I_HostDB.cc
+++ /dev/null
@@ -1,50 +0,0 @@
-/** @file
-
- A brief file description
-
- @section license License
-
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); 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 <stdio.h>
-#include "iocore/hostdb/HostDB.h"
-
-#include "iocore/utils/diags.i"
-
-class HostDBTest : Continuation
-{
-};
-
-int
-main()
-{
- init_diags("net_test", nullptr);
- ink_event_system_init(EVENT_SYSTEM_MODULE_PUBLIC_VERSION);
- ink_net_init(NET_SYSTEM_MODULE_PUBLIC_VERSION);
- ink_hostdb_init(HOSTDB_MODULE_PUBLIC_VERSION);
- signal(SIGPIPE, SIG_IGN);
-
- eventProcessor.start(2);
- netProcessor.start();
-
- printf("hello world\n");
-
- hostDBProcessor.start();
-
- this_ethread()->execute();
-}
diff --git a/src/iocore/hostdb/test_P_HostDB.cc
b/src/iocore/hostdb/test_P_HostDB.cc
deleted file mode 100644
index d7d408de9f..0000000000
--- a/src/iocore/hostdb/test_P_HostDB.cc
+++ /dev/null
@@ -1,82 +0,0 @@
-/** @file
-
- A brief file description
-
- @section license License
-
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); 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 "P_HostDB.h"
-
-Diags *diags;
-struct NetTesterSM : public Continuation {
- VIO *read_vio;
- IOBufferReader *reader;
- NetVConnection *vc;
- MIOBuffer *buf;
-
- NetTesterSM(ProxyMutex *_mutex, NetVConnection *_vc) : Continuation(_mutex)
- {
- MUTEX_TRY_LOCK(lock, mutex, _vc->thread);
- ink_release_assert(lock);
- vc = _vc;
- SET_HANDLER(&NetTesterSM::handle_read);
- buf = new_MIOBuffer(8);
- reader = buf->alloc_reader();
- read_vio = vc->do_io_read(this, INT64_MAX, buf);
- }
-
- int
- handle_read(int event, void *data)
- {
- int r;
- char *str;
- switch (event) {
- case VC_EVENT_READ_READY:
- r = reader->read_avail();
- str = new char[r + 10];
- reader->read(str, r);
- printf("%s", str);
- delete[] str;
- fflush(stdout);
- break;
- case VC_EVENT_READ_COMPLETE:
- /* FALLTHROUGH */
- case VC_EVENT_EOS:
- r = reader->read_avail();
- str = new char[r + 10];
- reader->read(str, r);
- printf("%s", str);
- delete[] str;
- fflush(stdout);
- case VC_EVENT_ERROR:
- vc->do_io_close();
- // fixme
- // handle timeout events
- break;
- default:
- ink_release_assert(!"unknown event");
- }
- return EVENT_CONT;
- }
-};
-
-int
-main()
-{
-}
diff --git a/src/iocore/hostdb/test_RefCountCache.cc
b/src/iocore/hostdb/test_RefCountCache.cc
index f06fdf872c..50d4c6b96f 100644
--- a/src/iocore/hostdb/test_RefCountCache.cc
+++ b/src/iocore/hostdb/test_RefCountCache.cc
@@ -22,10 +22,10 @@
*/
#include <iostream>
-#include <RefCountCache.cc>
+#include "RefCountCache.cc"
#include "iocore/eventsystem/EventSystem.h"
#include "tscore/Layout.h"
-#include <diags.i>
+#include "iocore/utils/diags.i"
#include <set>
// TODO: add tests with expiry_time