]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Multiplexer: Take the maximum number of events as a hint 11517/head
authorRemi Gacogne <remi.gacogne@powerdns.com>
Fri, 8 Apr 2022 09:30:48 +0000 (11:30 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Fri, 8 Apr 2022 09:30:48 +0000 (11:30 +0200)
This allows indicating the maximum number of events we want to process
in a single run, which is usually bounded by the number of file descriptors
we are planning on watching.
The default is still 1024 events, but this change makes it possible to
allocate a smaller vector of events to reduce the memory usage when we
know we are going to need to process so many events in a single run.

pdns/devpollmplexer.cc
pdns/epollmplexer.cc
pdns/kqueuemplexer.cc
pdns/mplexer.hh
pdns/pollmplexer.cc
pdns/portsmplexer.cc
pdns/recursordist/rec-main.cc
pdns/test-mplexer.cc

index 37a0d487fff60c37816822c9113c9bc1d4cb52ed..071ee9e94597a130789639b4ed1b0ddc8d43a32f 100644 (file)
@@ -62,7 +62,7 @@ private:
   int d_devpollfd;
 };
 
-static FDMultiplexer* makeDevPoll()
+static FDMultiplexer* makeDevPoll(unsigned int)
 {
   return new DevPollFDMultiplexer();
 }
index 85158d246f6879a4c2e9d3f3057c418e7090ed89..74de2c29607b2eba7a720769b987c0d451024924 100644 (file)
@@ -36,7 +36,7 @@
 class EpollFDMultiplexer : public FDMultiplexer
 {
 public:
-  EpollFDMultiplexer();
+  EpollFDMultiplexer(unsigned int maxEventsHint);
   ~EpollFDMultiplexer()
   {
     if (d_epollfd >= 0) {
@@ -59,12 +59,11 @@ public:
 private:
   int d_epollfd;
   std::vector<epoll_event> d_eevents;
-  static int s_maxevents; // not a hard maximum
 };
 
-static FDMultiplexer* makeEpoll()
+static FDMultiplexer* makeEpoll(unsigned int maxEventsHint)
 {
-  return new EpollFDMultiplexer();
+  return new EpollFDMultiplexer(maxEventsHint);
 }
 
 static struct EpollRegisterOurselves
@@ -75,12 +74,10 @@ static struct EpollRegisterOurselves
   }
 } doItEpoll;
 
-int EpollFDMultiplexer::s_maxevents = 1024;
-
-EpollFDMultiplexer::EpollFDMultiplexer() :
-  d_eevents(s_maxevents)
+EpollFDMultiplexer::EpollFDMultiplexer(unsigned int maxEventsHint) :
+  d_eevents(maxEventsHint)
 {
-  d_epollfd = epoll_create(s_maxevents); // not hard max
+  d_epollfd = epoll_create(static_cast<int>(maxEventsHint)); // not hard max, just a hint that is actually ignored since Linux 2.6.8
   if (d_epollfd < 0) {
     throw FDMultiplexerException("Setting up epoll: " + stringerror());
   }
@@ -156,7 +153,7 @@ void EpollFDMultiplexer::alterFD(int fd, FDMultiplexer::EventKind, FDMultiplexer
 
 void EpollFDMultiplexer::getAvailableFDs(std::vector<int>& fds, int timeout)
 {
-  int ret = epoll_wait(d_epollfd, d_eevents.data(), s_maxevents, timeout);
+  int ret = epoll_wait(d_epollfd, d_eevents.data(), d_eevents.size(), timeout);
 
   if (ret < 0 && errno != EINTR) {
     throw FDMultiplexerException("epoll returned error: " + stringerror());
@@ -173,7 +170,7 @@ int EpollFDMultiplexer::run(struct timeval* now, int timeout)
     throw FDMultiplexerException("FDMultiplexer::run() is not reentrant!\n");
   }
 
-  int ret = epoll_wait(d_epollfd, d_eevents.data(), s_maxevents, timeout);
+  int ret = epoll_wait(d_epollfd, d_eevents.data(), d_eevents.size(), timeout);
   gettimeofday(now, nullptr); // MANDATORY
 
   if (ret < 0 && errno != EINTR) {
index f777b8080819a63b1941dead3506cdddb92c8f15..2c426a69c7606d8b7366383d3c14f19cac32b8cf 100644 (file)
@@ -38,7 +38,7 @@
 class KqueueFDMultiplexer : public FDMultiplexer
 {
 public:
-  KqueueFDMultiplexer();
+  KqueueFDMultiplexer(unsigned int maxEventsHint);
   ~KqueueFDMultiplexer()
   {
     if (d_kqueuefd >= 0) {
@@ -60,14 +60,11 @@ public:
 private:
   int d_kqueuefd;
   std::vector<struct kevent> d_kevents;
-  static unsigned int s_maxevents; // not a hard maximum
 };
 
-unsigned int KqueueFDMultiplexer::s_maxevents = 1024;
-
-static FDMultiplexer* make()
+static FDMultiplexer* make(unsigned int maxEventsHint)
 {
-  return new KqueueFDMultiplexer();
+  return new KqueueFDMultiplexer(maxEventsHint);
 }
 
 static struct KqueueRegisterOurselves
@@ -78,8 +75,8 @@ static struct KqueueRegisterOurselves
   }
 } kQueueDoIt;
 
-KqueueFDMultiplexer::KqueueFDMultiplexer() :
-  d_kevents(s_maxevents)
+KqueueFDMultiplexer::KqueueFDMultiplexer(unsigned int maxEventsHint) :
+  d_kevents(maxEventsHint)
 {
   d_kqueuefd = kqueue();
   if (d_kqueuefd < 0) {
@@ -148,7 +145,7 @@ void KqueueFDMultiplexer::getAvailableFDs(std::vector<int>& fds, int timeout)
   ts.tv_sec = timeout / 1000;
   ts.tv_nsec = (timeout % 1000) * 1000000;
 
-  int ret = kevent(d_kqueuefd, 0, 0, d_kevents.data(), s_maxevents, &ts);
+  int ret = kevent(d_kqueuefd, 0, 0, d_kevents.data(), d_kevents.size(), &ts);
 
   if (ret < 0 && errno != EINTR) {
     throw FDMultiplexerException("kqueue returned error: " + stringerror());
@@ -177,7 +174,7 @@ int KqueueFDMultiplexer::run(struct timeval* now, int timeout)
   ts.tv_sec = timeout / 1000;
   ts.tv_nsec = (timeout % 1000) * 1000000;
 
-  int ret = kevent(d_kqueuefd, 0, 0, d_kevents.data(), s_maxevents, &ts);
+  int ret = kevent(d_kqueuefd, 0, 0, d_kevents.data(), d_kevents.size(), &ts);
   gettimeofday(now, nullptr); // MANDATORY!
 
   if (ret < 0 && errno != EINTR) {
index 9ff4ab18c1693f7a8680ac6fa05c36fbc2cfa8d8..bba581c31f8d5835a6e8a102570a3771b3d75a71 100644 (file)
@@ -76,7 +76,11 @@ public:
   virtual ~FDMultiplexer()
   {}
 
-  static FDMultiplexer* getMultiplexerSilent();
+  // The maximum number of events processed in a single run, not the maximum of watched descriptors
+  static constexpr unsigned int s_maxevents = 1024;
+  /* The maximum number of events processed in a single run will be capped to the
+     minimum value of maxEventsHint and s_maxevents, to reduce memory usage. */
+  static FDMultiplexer* getMultiplexerSilent(unsigned int maxEventsHint = s_maxevents);
 
   /* tv will be updated to 'now' before run returns */
   /* timeout is in ms */
@@ -206,7 +210,7 @@ public:
     return ret;
   }
 
-  typedef FDMultiplexer* getMultiplexer_t();
+  typedef FDMultiplexer* getMultiplexer_t(unsigned int);
   typedef std::multimap<int, getMultiplexer_t*> FDMultiplexermap_t;
 
   static FDMultiplexermap_t& getMultiplexerMap()
index 05ab28bf88c2eff389b3676843461a4116bb0635..70a660ba8930056b746aecbae637ef982e55189e 100644 (file)
@@ -9,12 +9,12 @@
 #include "misc.hh"
 #include "namespaces.hh"
 
-FDMultiplexer* FDMultiplexer::getMultiplexerSilent()
+FDMultiplexer* FDMultiplexer::getMultiplexerSilent(unsigned int maxEventsHint)
 {
   FDMultiplexer* ret = nullptr;
   for (const auto& i : FDMultiplexer::getMultiplexerMap()) {
     try {
-      ret = i.second();
+      ret = i.second(std::min(maxEventsHint, FDMultiplexer::s_maxevents));
       return ret;
     }
     catch (const FDMultiplexerException& fe) {
@@ -28,7 +28,7 @@ FDMultiplexer* FDMultiplexer::getMultiplexerSilent()
 class PollFDMultiplexer : public FDMultiplexer
 {
 public:
-  PollFDMultiplexer()
+  PollFDMultiplexer(unsigned int maxEventsHint)
   {}
   ~PollFDMultiplexer()
   {
@@ -50,9 +50,9 @@ private:
   vector<struct pollfd> preparePollFD() const;
 };
 
-static FDMultiplexer* make()
+static FDMultiplexer* make(unsigned int maxEventsHint)
 {
-  return new PollFDMultiplexer();
+  return new PollFDMultiplexer(maxEventsHint);
 }
 
 static struct RegisterOurselves
index f5e151043cee874ca8b427014bbfc86bbde61668..61333ef434ec3d6644eb0f1f42709a71a9b55b0a 100644 (file)
@@ -17,7 +17,7 @@
 class PortsFDMultiplexer : public FDMultiplexer
 {
 public:
-  PortsFDMultiplexer();
+  PortsFDMultiplexer(unsigned int maxEventsHint);
   ~PortsFDMultiplexer()
   {
     close(d_portfd);
@@ -37,10 +37,9 @@ public:
 private:
   int d_portfd;
   std::vector<port_event_t> d_pevents;
-  static int s_maxevents; // not a hard maximum
 };
 
-static FDMultiplexer* makePorts()
+static FDMultiplexer* makePorts(unsigned int)
 {
   return new PortsFDMultiplexer();
 }
@@ -53,10 +52,8 @@ static struct PortsRegisterOurselves
   }
 } doItPorts;
 
-int PortsFDMultiplexer::s_maxevents = 1024;
-
-PortsFDMultiplexer::PortsFDMultiplexer() :
-  d_pevents(s_maxevents)
+PortsFDMultiplexer::PortsFDMultiplexer(unsigned int maxEventsHint) :
+  d_pevents(maxEventsHint)
 {
   d_portfd = port_create(); // not hard max
   if (d_portfd < 0) {
@@ -97,7 +94,7 @@ void PortsFDMultiplexer::getAvailableFDs(std::vector<int>& fds, int timeout)
   timeoutspec.tv_sec = timeout / 1000;
   timeoutspec.tv_nsec = (timeout % 1000) * 1000000;
   unsigned int numevents = 1;
-  int ret = port_getn(d_portfd, d_pevents.data(), min(PORT_MAX_LIST, s_maxevents), &numevents, &timeoutspec);
+  int ret = port_getn(d_portfd, d_pevents.data(), min(PORT_MAX_LIST, d_pevents.size()), &numevents, &timeoutspec);
 
   /* port_getn has an unusual API - (ret == -1, errno == ETIME) can
      mean partial success; you must check (*numevents) in this case
@@ -158,7 +155,7 @@ int PortsFDMultiplexer::run(struct timeval* now, int timeout)
   timeoutspec.tv_sec = timeout / 1000;
   timeoutspec.tv_nsec = (timeout % 1000) * 1000000;
   unsigned int numevents = 1;
-  int ret = port_getn(d_portfd, d_pevents.data(), min(PORT_MAX_LIST, s_maxevents), &numevents, &timeoutspec);
+  int ret = port_getn(d_portfd, d_pevents.data(), min(PORT_MAX_LIST, d_pevents.size()), &numevents, &timeoutspec);
 
   /* port_getn has an unusual API - (ret == -1, errno == ETIME) can
      mean partial success; you must check (*numevents) in this case
index aed5c66b7d7b83fdac0698d86274f4ad79099b19..ba6c1a48c7d3a0ad8b85697419314da309e3e6bc 100644 (file)
@@ -340,7 +340,7 @@ static FDMultiplexer* getMultiplexer()
   FDMultiplexer* ret;
   for (const auto& i : FDMultiplexer::getMultiplexerMap()) {
     try {
-      ret = i.second();
+      ret = i.second(FDMultiplexer::s_maxevents);
       return ret;
     }
     catch (FDMultiplexerException& fe) {
index 7fe483d4bd7930c095cff905b9361b9bc78542ce..327eb39d22608701f880373706f10d33df22e60c 100644 (file)
@@ -24,7 +24,7 @@ BOOST_AUTO_TEST_CASE(test_getMultiplexerSilent)
 BOOST_AUTO_TEST_CASE(test_MPlexer)
 {
   for (const auto& entry : FDMultiplexer::getMultiplexerMap()) {
-    auto mplexer = std::unique_ptr<FDMultiplexer>(entry.second());
+    auto mplexer = std::unique_ptr<FDMultiplexer>(entry.second(FDMultiplexer::s_maxevents));
     BOOST_REQUIRE(mplexer != nullptr);
     //cerr<<"Testing multiplexer "<<mplexer->getName()<<endl;
 
@@ -224,7 +224,7 @@ BOOST_AUTO_TEST_CASE(test_MPlexer)
 BOOST_AUTO_TEST_CASE(test_MPlexer_ReadAndWrite)
 {
   for (const auto& entry : FDMultiplexer::getMultiplexerMap()) {
-    auto mplexer = std::unique_ptr<FDMultiplexer>(entry.second());
+    auto mplexer = std::unique_ptr<FDMultiplexer>(entry.second(FDMultiplexer::s_maxevents));
     BOOST_REQUIRE(mplexer != nullptr);
     //cerr<<"Testing multiplexer "<<mplexer->getName()<<" for read AND write"<<endl;