Date: Mon, 24 Jan 2000 10:11:03 -0800 From: "Scott Hess" <scott@avantgo.com> To: <freebsd-hackers@freebsd.org> Subject: Performance issue with rfork() and single socketpairs versus multiple socketpairs. Message-ID: <01b601bf6696$60701930$1e80000a@avantgo.com>
next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format. ------=_NextPart_000_01B3_01BF6653.523EF680 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit I've found an odd performance issue that I cannot explain. I'm using socketpairs to communicate with multiple rfork(RFPROC) processes. Initially, I used a seperate socketpair to communicate requests to each process, with locking in the parent to synchronize access to each client. I determined that by using a single socketpair, I could save on all the socketpairs, and also perhaps improve performance by allowing more requests to be dispatched than there were processes to handle them. Whenever a worker process finished one request, it would immediately be able to start the next, without having to wait for the parent to receive the response and reprocess the request structures. Unfortunately, I've found that having a group of processes reading from a group of socketpairs has better performance than having them all read from a single socketpair. I've been unable to determine why. I've reduced the problem down to a simple program, included as an attachment (sorry about that). The results of two runs of the program: ganja% time ./commtest --single ./commtest --single 0.00s user 0.66s system 15% cpu 4.132 total ganja% time ./commtest --multi ./commtest --multi 0.00s user 0.46s system 68% cpu 0.675 total Note that in the --single case, the system time rises a bit - but the wallclock time rises a _lot_. At first I thought this was a variant on the "thundering herd" problem, but the CPU times taken don't seem to bear this out. Any ideas? Running under 3.2-RELEASE on an SMP machine, though I saw the same results on 3.4-RELEASE. Thanks, scott ------=_NextPart_000_01B3_01BF6653.523EF680 Content-Type: application/octet-stream; name="commtest.c" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="commtest.c" // commtest.c=0A= // gcc -Wall -g -o commtest commtest.c=0A= //=0A= // Test performance differences for multiple socketpairs versus a=0A= // single shared socketpair.=0A= #include <unistd.h>=0A= #include <stdio.h>=0A= #include <stdlib.h>=0A= #include <fcntl.h>=0A= #include <sys/types.h>=0A= #include <sys/socket.h>=0A= #include <string.h>=0A= #include <errno.h>=0A= =0A= typedef unsigned char request_t;=0A= =0A= #define CLIENT_EXIT ((request_t)(~0))=0A= #define CLIENT_COUNT 32=0A= #define REQUEST_TARGET 10000=0A= =0A= int client_fd_count=3D0;=0A= int client_fds[ CLIENT_COUNT];=0A= int server_fds[ CLIENT_COUNT];=0A= =0A= /* Reflect requests. */=0A= void client( int fd)=0A= {=0A= request_t request;=0A= int rc;=0A= =0A= while( 1) {=0A= if( (rc=3Dread( fd, &request, sizeof( request)))=3D=3D-1) {=0A= perror( "client read");=0A= _exit( 1);=0A= } else if( rc<sizeof( request)) {=0A= _exit( 0);=0A= } else if( (rc=3Dwrite( fd, &request, sizeof( = request)))=3D=3D-1) {=0A= perror( "client write");=0A= _exit( 1);=0A= } else if( rc<sizeof( request)) {=0A= _exit( 0);=0A= }=0A= }=0A= }=0A= =0A= void main( int argc, char **argv)=0A= {=0A= int ii, flags, maxfd, rc;=0A= int pair[ 2];=0A= fd_set default_fdset, fdset;=0A= pid_t cpid;=0A= request_t request;=0A= int request_count=3D0;=0A= =0A= client_fd_count=3D1;=0A= if( argc=3D=3D2 && !strcmp( argv[ 1], "--multi")) {=0A= client_fd_count=3DCLIENT_COUNT;=0A= } else if( argc=3D=3D2 && !strcmp( argv[ 1], "--single")) {=0A= client_fd_count=3D1;=0A= } else if( argc=3D=3D2 && !strcmp( argv[ 1], "--handful")) {=0A= client_fd_count=3D4;=0A= }=0A= =0A= maxfd=3D0;=0A= FD_ZERO( &default_fdset);=0A= for( ii=3D0; ii<client_fd_count; ii++) {=0A= if( socketpair(AF_UNIX,SOCK_STREAM,0,pair)=3D=3D-1) {=0A= perror( "creating socketpair");=0A= goto err_exit;=0A= } else if( (flags=3Dfcntl( pair[ 0], F_GETFL, NULL))=3D=3D-1) {=0A= perror( "getting flags");=0A= goto err_exit;=0A= } else if( fcntl( pair[ 0], F_SETFL, flags|O_NONBLOCK)=3D=3D-1) {=0A= perror( "setting flags");=0A= goto err_exit;=0A= }=0A= =0A= client_fds[ ii]=3Dpair[ 0];=0A= server_fds[ ii]=3Dpair[ 1];=0A= =0A= FD_SET( client_fds[ ii], &default_fdset);=0A= if( client_fds[ ii]>maxfd) {=0A= maxfd=3Dclient_fds[ ii];=0A= }=0A= }=0A= =0A= /* Spin off children to process requests. */=0A= for( ii=3D0; ii<CLIENT_COUNT; ii++) {=0A= if( (cpid=3Drfork(RFPROC))=3D=3D-1) {=0A= perror( "rfork");=0A= goto err_exit;=0A= } else if( cpid=3D=3D0) {=0A= client( server_fds[ ii%client_fd_count]);=0A= } else {=0A= request=3Dii;=0A= if( write( client_fds[ ii%client_fd_count], &request, = sizeof( request))=3D=3D-1) {=0A= perror( "writing initial request");=0A= goto err_exit;=0A= }=0A= }=0A= }=0A= =0A= while( request_count<REQUEST_TARGET) {=0A= fdset=3Ddefault_fdset;=0A= select( maxfd+1, &fdset, NULL, &fdset, NULL);=0A= =0A= for( ii=3D0; ii<client_fd_count && request_count<REQUEST_TARGET; = ii++) {=0A= while( (rc=3Dread( client_fds[ ii], &request, sizeof( = request)))=3D=3Dsizeof( request) && request_count<REQUEST_TARGET) {=0A= if( write( client_fds[ ii], &request, sizeof( = request))=3D=3D-1) {=0A= perror( "writing request");=0A= goto err_exit;=0A= }=0A= request_count++;=0A= }=0A= if( rc=3D=3D-1 && errno!=3DEAGAIN && errno!=3DEWOULDBLOCK) {=0A= perror( "reading response");=0A= goto err_exit;=0A= }=0A= }=0A= }=0A= =0A= for( ii=3D0; ii<client_fd_count; ii++) {=0A= close( client_fds[ ii]);=0A= }=0A= exit( 0);=0A= =0A= err_exit:=0A= for( ii=3D0; ii<client_fd_count; ii++) {=0A= close( client_fds[ ii]);=0A= }=0A= exit( 1);=0A= }=0A= ------=_NextPart_000_01B3_01BF6653.523EF680-- To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?01b601bf6696$60701930$1e80000a>