]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: fd: delete unused updates on close()
authorWilly Tarreau <w@1wt.eu>
Wed, 6 Jul 2022 14:20:11 +0000 (16:20 +0200)
committerWilly Tarreau <w@1wt.eu>
Fri, 15 Jul 2022 17:58:06 +0000 (19:58 +0200)
After a poller's ->clo() was called to completely terminate operations
on an FD, there's no reason for keeping updates on this FD, so if any
updates were already programmed it would be nice if we could delete them.

Tests show that __fd_clo() is called roughly half of the time with the
last FD from the local update list, which possibly makes sense if a close
has to appear after a polling change resulting from an incomplete read or
the end of a send().

We can detect this and remove the last entry, which gives less work to
do during the update() call, and eliminates most of the poll_drop_fd
event reports.

Note that while tempting, this must not be backported because it's only
safe to be done now that fd_delete_orphan() clears the update mask as
we need to be certain not to miss it:
  - if the update mask is kept up with no entry, we can miss future
    updates ;
  - if the update mask is cleared too fast, it may result in failure
    to add a shared event.

src/fd.c

index 6ea3d2ca9d92eb635f2816961d1b98f25380ef9b..9757d0ad7d303ecd433e805a93f521b39d8db36a 100644 (file)
--- a/src/fd.c
+++ b/src/fd.c
@@ -322,6 +322,8 @@ void _fd_delete_orphan(int fd)
 
        /* no more updates on this FD are relevant anymore */
        HA_ATOMIC_STORE(&fdtab[fd].update_mask, 0);
+       if (fd_nbupdt > 0 && fd_updt[fd_nbupdt - 1] == fd)
+               fd_nbupdt--;
 
        port_range_release_port(fdinfo[fd].port_range, fdinfo[fd].local_port);
        polled_mask[fd].poll_recv = polled_mask[fd].poll_send = 0;