accept: Implement fast soaccept predication
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Thu, 24 Nov 2011 05:53:54 +0000 (13:53 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Thu, 24 Nov 2011 06:32:15 +0000 (14:32 +0800)
Fast soaccept predication tries to run soaccept_predicate before
domsg to the proto-thread, i.e. put the current thread into sleep.

We could do this because listen socket's completion list is always
protected by the listen socket's pool-token.  Domsg to proto-thread
to extract socket from completion list for non-block listen socket
does not make any sense.  Even for blocking listen socket if there
are sockets on the completion list, domsg to the proto-thread to
extract socket from completion list also wastes time.

The result:

192.168.249.42 (Xeon E3-1230 HT enabled, 16G) runs httperf
192.168.249.29 (i7-2600 HT enabled, 16G) runs nginx (web server)

The server runs nginx-1.0.4 (from pkgsrc-2011Q2), using the default
configure w/ following changes:
events {
    worker_connections  10240;
    use kqueue;
}

The client runs httperf-0.9.0 manually compiled w/ FD_SETSIZE to 16424
The client machine runs following commands before starting benching:
net.inet.ip.portrange.last=60000
route change -net 192.168.249.0/24 -msl 500

16 parallel httperf --server=192.168.249.29 --wsess=5000,1,1 --max-conn=4
4 runs (Request rate, unit: req/s)

old  23554.0  23542.0  23557.0  23526.2
new  24793.7  24809.9  24792.7  24794.4

This gives 5.3% performance improvement

sys/kern/uipc_socket.c
sys/kern/uipc_syscalls.c

index 5a21de3..6620fb1 100644 (file)
@@ -137,6 +137,10 @@ static int use_soclose_fast = 1;
 SYSCTL_INT(_kern_ipc, OID_AUTO, soclose_fast, CTLFLAG_RW,
     &use_soclose_fast, 0, "Fast socket close");
 
+int use_soaccept_pred_fast = 1;
+SYSCTL_INT(_kern_ipc, OID_AUTO, soaccept_pred_fast, CTLFLAG_RW,
+    &use_soaccept_pred_fast, 0, "Fast socket accept predication");
+
 /*
  * Socket operation routines.
  * These routines are called by the routines in
index 9b87fe2..cdb3bf1 100644 (file)
@@ -84,6 +84,8 @@
 #include <netinet/sctp_peeloff.h>
 #endif /* SCTP */
 
+extern int use_soaccept_pred_fast;
+
 /*
  * System call interface to the socket abstraction.
  */
@@ -296,6 +298,26 @@ kern_accept(int s, int fflags, struct sockaddr **name, int *namelen, int *res)
        else
                fflags = lfp->f_flag;
 
+       if (use_soaccept_pred_fast) {
+               boolean_t pred;
+
+               /* Initialize necessary parts for soaccept_predicate() */
+               netmsg_init(&msg.base, head, &netisr_apanic_rport, 0, NULL);
+               msg.nm_fflags = fflags;
+
+               lwkt_getpooltoken(head);
+               pred = soaccept_predicate(&msg);
+               lwkt_relpooltoken(head);
+
+               if (pred) {
+                       error = msg.base.lmsg.ms_error;
+                       if (error)
+                               goto done;
+                       else
+                               goto accepted;
+               }
+       }
+
        /* optimize for uniprocessor case later XXX JH */
        netmsg_init_abortable(&msg.base, head, &curthread->td_msgport,
                              0, netmsg_so_notify, netmsg_so_notify_doabort);
@@ -306,6 +328,7 @@ kern_accept(int s, int fflags, struct sockaddr **name, int *namelen, int *res)
        if (error)
                goto done;
 
+accepted:
        /*
         * At this point we have the connection that's ready to be accepted.
         *