Skip site navigation (1)Skip section navigation (2)
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
This is a multi-part message in MIME format.

------=_NextPart_000_0C1E_01BF6710.C075B360
Content-Type: text/plain;
	charset="iso-8859-1"
Content-Transfer-Encoding: 7bit

"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


------=_NextPart_000_0C1E_01BF6710.C075B360
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 versus SYSV semaphores.=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=
#include <sys/sem.h>=0A=
#include <sys/ipc.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 socket_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=
void sem_client( int sem, int sem_id, int fd, request_t rid)=0A=
{=0A=
    struct sembuf sem_req=3D{ sem_id, -1, 0};=0A=
    int rc;=0A=
    =0A=
    while( 1) {=0A=
	if( (rc=3Dsemop( sem, &sem_req, 1))=3D=3D-1) {=0A=
            perror( "client semop");=0A=
            _exit( 1);=0A=
        } else if( (rc=3Dwrite( fd, &rid, sizeof( rid)))=3D=3D-1) {=0A=
            perror( "client write");=0A=
            _exit( 1);=0A=
        } else if( rc<sizeof( rid)) {=0A=
            _exit( 0);=0A=
        }=0A=
    }=0A=
}=0A=
=0A=
void main( int argc, char **argv)=0A=
{=0A=
    int ii, jj, flags, maxfd, rc;=0A=
    int pair[ 2];=0A=
    fd_set default_fdset, fdset;=0A=
    pid_t cpid;=0A=
    request_t request[32];=0A=
    int request_count=3D0;=0A=
    int sem=3D-1;=0A=
    int sem_count=3D-1;=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=
    } else if( argc=3D=3D2 && !strcmp( argv[ 1], "--sem")) {=0A=
	sem_count=3D1;=0A=
    } else if( argc=3D=3D2 && !strcmp( argv[ 1], "--semulti")) {=0A=
	sem_count=3DCLIENT_COUNT;=0A=
    }=0A=
    =0A=
    if( sem_count>-1) {=0A=
	sem=3Dsemget( IPC_PRIVATE, sem_count, SEM_R|SEM_A);=0A=
	if( sem=3D=3D-1) {=0A=
	    perror( "semget");=0A=
	    exit( 1);=0A=
	}=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=
	    if( sem!=3D-1) {=0A=
		sem_client( sem, ii%sem_count, server_fds[ ii%client_fd_count], ii);=0A=
	    } else {=0A=
		socket_client( server_fds[ ii%client_fd_count]);=0A=
	    }=0A=
        } else {=0A=
            request[0]=3Dii;=0A=
	    if( sem!=3D-1) {=0A=
		struct sembuf sem_req=3D{ ii%sem_count, 1, 0};=0A=
		if( semop( sem, &sem_req, 1)=3D=3D-1) {=0A=
		    perror( "semop");=0A=
		    goto err_exit;=0A=
		}=0A=
            } else if( write( client_fds[ ii%client_fd_count], =
&(request[0]), sizeof( request[0]))=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=
            if( (rc=3Dread( client_fds[ ii], request, sizeof( =
request)))=3D=3D-1) {=0A=
		if( rc=3D=3D-1 && errno!=3DEAGAIN && errno!=3DEWOULDBLOCK) {=0A=
		    perror( "reading response");=0A=
		    goto err_exit;=0A=
		}=0A=
	    } else {=0A=
		jj=3Drc/sizeof( request[ 0]);=0A=
		while( jj--) {=0A=
		    if( sem!=3D-1) {=0A=
			struct sembuf sem_req=3D{ request[jj]%sem_count, 1, 0};=0A=
			if( semop( sem, &sem_req, 1)=3D=3D-1) {=0A=
			    perror( "semop");=0A=
			    goto err_exit;=0A=
			}=0A=
		    } else if( write( client_fds[ ii], &(request[jj]), sizeof( =
request[jj]))=3D=3D-1) {=0A=
			perror( "writing request");=0A=
			goto err_exit;=0A=
		    }=0A=
		    request_count++;=0A=
		}=0A=
            }=0A=
        }=0A=
    }=0A=
    =0A=
    if( sem!=3D-1) {=0A=
	semctl( sem, 0, IPC_RMID);=0A=
    }=0A=
    for( ii=3D0; ii<client_fd_count; ii++) {=0A=
        close( client_fds[ ii]);=0A=
    }=0A=
    exit( 0);=0A=
=0A=
err_exit:=0A=
    if( sem!=3D-1) {=0A=
	semctl( sem, 0, IPC_RMID);=0A=
    }=0A=
    for( ii=3D0; ii<client_fd_count; ii++) {=0A=
        close( client_fds[ ii]);=0A=
    }=0A=
    exit( 1);=0A=
}=0A=

------=_NextPart_000_0C1E_01BF6710.C075B360--



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?0c2101bf6753$cf37f280$1e80000a>