From 5e4b399478dd637a5a3939ddd2ebb4c5cffd3138 Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Thu, 24 Nov 2011 13:53:54 +0800 Subject: [PATCH] accept: Implement fast soaccept predication 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 | 4 ++++ sys/kern/uipc_syscalls.c | 23 +++++++++++++++++++++++ 2 files changed, 27 insertions(+), 0 deletions(-) diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index 5a21de3..6620fb1 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -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 diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c index 9b87fe2..cdb3bf1 100644 --- a/sys/kern/uipc_syscalls.c +++ b/sys/kern/uipc_syscalls.c @@ -84,6 +84,8 @@ #include #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. * -- 1.7.7.2