Walking a linked list to find an idle thread is not CPU cache- friendly, and in fact I've noted palpable per-request latency impacts as the number of nfsd threads on the server increases. After discussing some possible improvements with Jeff at LSF/MM, I've been experimenting with the following series. I've measured an order of magnitude latency improvement in the thread lookup time, and have managed to keep the whole thing lockless. After some offline discussion with Neil, I tried out using just the xarray plus its spinlock to mark threads idle or busy. This worked as well as the bitmap for lower thread counts, but got predictably bad as the thread count when past several hundred. For the moment I'm sticking with the wait-free bitmap lookup. Also, the maximum thread count is now 4096. I'm still willing to try an RCU-based bitmap resizing mechanism if we believe this is still to small of a maximum. Changes since RFC: * Add a counter for ingress RPC messages * Add a few documenting comments * Move the more controversial patches to the end of the series * Clarify the refactoring of svc_wake_up() * Increase the value of RPCSVC_MAXPOOLTHREADS to 4096 (and tested with that many threads) * Optimize the loop in svc_pool_wake_idle_thread() * Optimize marking a thread "idle" in svc_get_next_xprt() --- Chuck Lever (9): SUNRPC: Deduplicate thread wake-up code SUNRPC: Report when no service thread is available. SUNRPC: Split the svc_xprt_dequeue tracepoint SUNRPC: Count ingress RPC messages per svc_pool SUNRPC: Clean up svc_set_num_threads SUNRPC: Replace dprintk() call site in __svc_create() SUNRPC: Don't disable BH's when taking sp_lock SUNRPC: Replace sp_threads_all with an xarray SUNRPC: Convert RQ_BUSY into a per-pool bitmap fs/nfsd/nfssvc.c | 3 +- include/linux/sunrpc/svc.h | 18 ++-- include/trace/events/sunrpc.h | 159 +++++++++++++++++++++++++++---- net/sunrpc/svc.c | 174 ++++++++++++++++++++++------------ net/sunrpc/svc_xprt.c | 114 +++++++++++----------- 5 files changed, 328 insertions(+), 140 deletions(-) -- Chuck Lever