the current apr_pollset_remove has an O(n**2) scaling issue which is likely to degrade the perfomance of the httpd Event MPM when it is handling lots of connections. I've been playing with the following patch off and on but never posted it before due to day job pressures. it serves pages for me but hasn't been stress tested.

the basic idea is to exploit the fact that the internal pfd_elem_t and apr_pollfd_t occupy the same chunk of memory. by twiddling the internal structure, the pointer to one is the pointer to both and no search is needed. this only changes the epoll implementation; kqueue looks like it could work the same.

comments?

Greg
Index: ../apr/include/arch/unix/apr_arch_poll_private.h
===================================================================
--- ../apr/include/arch/unix/apr_arch_poll_private.h	(revision 492706)
+++ ../apr/include/arch/unix/apr_arch_poll_private.h	(working copy)
@@ -91,8 +91,8 @@
 typedef struct pfd_elem_t pfd_elem_t;
 
 struct pfd_elem_t {
+    apr_pollfd_t pfd;
     APR_RING_ENTRY(pfd_elem_t) link;
-    apr_pollfd_t pfd;
 };
 
 #endif
Index: ../apr/poll/unix/epoll.c
===================================================================
--- ../apr/poll/unix/epoll.c	(revision 492706)
+++ ../apr/poll/unix/epoll.c	(working copy)
@@ -219,18 +219,10 @@
         pollset_lock_rings();
 
         if (!APR_RING_EMPTY(&(pollset->query_ring), pfd_elem_t, link)) {
-            for (ep = APR_RING_FIRST(&(pollset->query_ring));
-                 ep != APR_RING_SENTINEL(&(pollset->query_ring),
-                                         pfd_elem_t, link);
-                 ep = APR_RING_NEXT(ep, link)) {
+            ep = (pfd_elem_t *) descriptor;
                 
-                if (descriptor->desc.s == ep->pfd.desc.s) {
-                    APR_RING_REMOVE(ep, link);
-                    APR_RING_INSERT_TAIL(&(pollset->dead_ring),
-                                         ep, pfd_elem_t, link);
-                    break;
-                }
-            }
+            APR_RING_REMOVE(ep, link);
+            APR_RING_INSERT_TAIL(&(pollset->dead_ring), ep, pfd_elem_t, link);
         }
 
         pollset_unlock_rings();

Reply via email to