From 60d691fbc6520f1f818ea523b1636e305043e366 Mon Sep 17 00:00:00 2001 From: Otto Moerbeek Date: Wed, 8 Nov 2023 11:05:49 +0100 Subject: [PATCH] rec: be more memory efficient handling RPZ reloads There were two things non-optimal: - The old zone contents is being kept in memory during a sleep for the next iteration and then thrown away. Fix: throw away before the sleep. - The Lua config is kept alive. This causes refs to old config data to stay around until all RPZ threads have cleared that config. Fix that by making the config loop-local and load it after the sleep call. Above claims confirmed by adding some debug code showing the ref counts for a config with many RPZs. --- pdns/recursordist/rpzloader.cc | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/pdns/recursordist/rpzloader.cc b/pdns/recursordist/rpzloader.cc index fb6eb04463..9ebae34c21 100644 --- a/pdns/recursordist/rpzloader.cc +++ b/pdns/recursordist/rpzloader.cc @@ -389,12 +389,10 @@ void RPZIXFRTracker(const std::vector& primaries, const boost::opt { setThreadName("rec/rpzixfr"); bool isPreloaded = sr != nullptr; - auto luaconfsLocal = g_luaconfs.getLocal(); - auto logger = g_slog->withName("rpz"); /* we can _never_ modify this zone directly, we need to do a full copy then replace the existing zone */ - std::shared_ptr oldZone = luaconfsLocal->dfe.getZone(zoneIdx); + std::shared_ptr oldZone = g_luaconfs.getLocal()->dfe.getZone(zoneIdx); if (!oldZone) { SLOG(g_log << Logger::Error << "Unable to retrieve RPZ zone with index " << zoneIdx << " from the configuration, exiting" << endl, logger->error(Logr::Error, "Unable to retrieve RPZ zone from configuration", "index", Logging::Loggable(zoneIdx))); @@ -444,7 +442,8 @@ void RPZIXFRTracker(const std::vector& primaries, const boost::opt incRPZFailedTransfers(polName); } } - + // Release newZone before (long) sleep to reduce memory usage + newZone = nullptr; if (!sr) { sleep(refresh); } @@ -453,6 +452,8 @@ void RPZIXFRTracker(const std::vector& primaries, const boost::opt bool skipRefreshDelay = isPreloaded; for (;;) { + // Don't hold on to oldZone, it well be re-assigned after sleep in the try block + oldZone = nullptr; DNSRecord dr; dr.setContent(sr); @@ -462,6 +463,7 @@ void RPZIXFRTracker(const std::vector& primaries, const boost::opt else { sleep(refresh); } + auto luaconfsLocal = g_luaconfs.getLocal(); if (luaconfsLocal->generation != configGeneration) { /* the configuration has been reloaded, meaning that a new thread -- 2.47.2