Date: Tue, 25 Jan 2000 08:47:03 -0800 From: "Scott Hess" <scott@avantgo.com> To: "Scott Hess" <scott@avantgo.com>, "Matthew Dillon" <dillon@apollo.backplane.com> Cc: <freebsd-hackers@FreeBSD.ORG> Subject: Re: Performance issue with rfork() and single socketpairs versus multiple socketpairs. Message-ID: <0c2101bf6753$cf37f280$1e80000a@avantgo.com> References: <01b601bf6696$60701930$1e80000a@avantgo.com> <200001241939.LAA91219@apollo.backplane.com> <0be801bf6715$601423d0$1e80000a@avantgo.com>
next in thread | previous in thread | raw e-mail | index | archive | help
[-- Attachment #1 --] "Scott Hess" <scott@avantgo.com> wrote: > "Matthew Dillon" <dillon@apollo.backplane.com> wrote: > > :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. > > > > The problem is that when you have N processes waiting on a single > > socket and you write to the socket, all N processes will wake up even > > though only one will get the data you wrote. > <snip> > > As an alternative to socket pairs, I would consider using SysV shared > > memory and SysV semaphores. > > OK, so let's say I did spend some time implementing it in terms of semget() > and semop(). Would you be totally apalled if the performance turned out to > be about the same as using a single socketpair? <snip> >Unfortunately, I'll have to wait until tomorrow morning >to rip things out and make a suitable example program for posting. Find attached a new version of commtest.c which uses semaphores. I've also placed a copy at http://www.doubleu.com/~scott/commtest.c. The performance is identical enough that I'm guessing that semaphores must suffer from the exact same problems as the single socketpair version. Thanks, scott [-- Attachment #2 --] // commtest.c // gcc -Wall -g -o commtest commtest.c // // Test performance differences for multiple socketpairs versus a // single shared socketpair versus SYSV semaphores. #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <sys/types.h> #include <sys/socket.h> #include <string.h> #include <errno.h> #include <sys/sem.h> #include <sys/ipc.h> typedef unsigned char request_t; #define CLIENT_EXIT ((request_t)(~0)) #define CLIENT_COUNT 32 #define REQUEST_TARGET 10000 int client_fd_count=0; int client_fds[ CLIENT_COUNT]; int server_fds[ CLIENT_COUNT]; /* Reflect requests. */ void socket_client( int fd) { request_t request; int rc; while( 1) { if( (rc=read( fd, &request, sizeof( request)))==-1) { perror( "client read"); _exit( 1); } else if( rc<sizeof( request)) { _exit( 0); } else if( (rc=write( fd, &request, sizeof( request)))==-1) { perror( "client write"); _exit( 1); } else if( rc<sizeof( request)) { _exit( 0); } } } void sem_client( int sem, int sem_id, int fd, request_t rid) { struct sembuf sem_req={ sem_id, -1, 0}; int rc; while( 1) { if( (rc=semop( sem, &sem_req, 1))==-1) { perror( "client semop"); _exit( 1); } else if( (rc=write( fd, &rid, sizeof( rid)))==-1) { perror( "client write"); _exit( 1); } else if( rc<sizeof( rid)) { _exit( 0); } } } void main( int argc, char **argv) { int ii, jj, flags, maxfd, rc; int pair[ 2]; fd_set default_fdset, fdset; pid_t cpid; request_t request[32]; int request_count=0; int sem=-1; int sem_count=-1; client_fd_count=1; if( argc==2 && !strcmp( argv[ 1], "--multi")) { client_fd_count=CLIENT_COUNT; } else if( argc==2 && !strcmp( argv[ 1], "--single")) { client_fd_count=1; } else if( argc==2 && !strcmp( argv[ 1], "--handful")) { client_fd_count=4; } else if( argc==2 && !strcmp( argv[ 1], "--sem")) { sem_count=1; } else if( argc==2 && !strcmp( argv[ 1], "--semulti")) { sem_count=CLIENT_COUNT; } if( sem_count>-1) { sem=semget( IPC_PRIVATE, sem_count, SEM_R|SEM_A); if( sem==-1) { perror( "semget"); exit( 1); } } maxfd=0; FD_ZERO( &default_fdset); for( ii=0; ii<client_fd_count; ii++) { if( socketpair(AF_UNIX,SOCK_STREAM,0,pair)==-1) { perror( "creating socketpair"); goto err_exit; } else if( (flags=fcntl( pair[ 0], F_GETFL, NULL))==-1) { perror( "getting flags"); goto err_exit; } else if( fcntl( pair[ 0], F_SETFL, flags|O_NONBLOCK)==-1) { perror( "setting flags"); goto err_exit; } client_fds[ ii]=pair[ 0]; server_fds[ ii]=pair[ 1]; FD_SET( client_fds[ ii], &default_fdset); if( client_fds[ ii]>maxfd) { maxfd=client_fds[ ii]; } } /* Spin off children to process requests. */ for( ii=0; ii<CLIENT_COUNT; ii++) { if( (cpid=rfork(RFPROC))==-1) { perror( "rfork"); goto err_exit; } else if( cpid==0) { if( sem!=-1) { sem_client( sem, ii%sem_count, server_fds[ ii%client_fd_count], ii); } else { socket_client( server_fds[ ii%client_fd_count]); } } else { request[0]=ii; if( sem!=-1) { struct sembuf sem_req={ ii%sem_count, 1, 0}; if( semop( sem, &sem_req, 1)==-1) { perror( "semop"); goto err_exit; } } else if( write( client_fds[ ii%client_fd_count], &(request[0]), sizeof( request[0]))==-1) { perror( "writing initial request"); goto err_exit; } } } while( request_count<REQUEST_TARGET) { fdset=default_fdset; select( maxfd+1, &fdset, NULL, &fdset, NULL); for( ii=0; ii<client_fd_count && request_count<REQUEST_TARGET; ii++) { if( (rc=read( client_fds[ ii], request, sizeof( request)))==-1) { if( rc==-1 && errno!=EAGAIN && errno!=EWOULDBLOCK) { perror( "reading response"); goto err_exit; } } else { jj=rc/sizeof( request[ 0]); while( jj--) { if( sem!=-1) { struct sembuf sem_req={ request[jj]%sem_count, 1, 0}; if( semop( sem, &sem_req, 1)==-1) { perror( "semop"); goto err_exit; } } else if( write( client_fds[ ii], &(request[jj]), sizeof( request[jj]))==-1) { perror( "writing request"); goto err_exit; } request_count++; } } } } if( sem!=-1) { semctl( sem, 0, IPC_RMID); } for( ii=0; ii<client_fd_count; ii++) { close( client_fds[ ii]); } exit( 0); err_exit: if( sem!=-1) { semctl( sem, 0, IPC_RMID); } for( ii=0; ii<client_fd_count; ii++) { close( client_fds[ ii]); } exit( 1); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?0c2101bf6753$cf37f280$1e80000a>
