Test program: DU good Linux bad

Jim Nance (jlnance@avanticorp.com)
Thu, 6 May 1999 09:50:10 -0400


Hello All,
I was playing around with an idea for avoiding the "thundering herd"
problem on select/accept, and I think I found a similar problem on read().
I thought it was worth posting about because neigher Digital Unix nor
Solaris has this problem so that probably means its fixable.
The program creates a pipe and forks off a number of children. Each of
these children tries to read an int from the pipe, decrement it and write it
back into the pipe. When the int goes to zero the program stops and prints
its results. The times I get for 5000000 iterations are:

Processes Linux(sec) Dig Unix(sec) Solaris(sec)
2 16.775 23.223 41.774
25 45.589 25.022 43.158
50 87.721 23.707 43.008

Linux 2.2.7 333Mhz PII 500M ram
Digital Unix 4.0D 600Mhz 21164 1.5G ram
Solaris 5.6

On thing I notice is that both DU and Solaris spread the load across all
the processes, while linux gives most of the work to a few processes.

The program is included below. As an example of its command line opts:
./a.out -iter=5000000 -proc=50

/* This tests an idea for wakeing up processes */

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/time.h>

static pid_t parrent_pid;
static int got_usr1=0;

void retme(int x) {got_usr1=1;}

void looper(int pipefd[2])
{
while(1) {
int rval;
int nbytes = read(pipefd[0], &rval, sizeof(rval));

if(nbytes==sizeof(rval)) {
--rval;
if(rval<=0) {
kill(parrent_pid, SIGUSR1);
} else {
write(pipefd[1], &rval, sizeof(rval));
}
} else if(nbytes>0 && nbytes!=sizeof(rval)) {
fprintf(stderr, "I thought this was impossible\n");
} else {
fprintf(stderr, "Empty read\n");
}
}
}

void parse_cmdline(int ac, char *av[], int *rval, int *mproc)
{
int idx;
int tmp;
char str1[] = "-proc=";
char str2[] = "-iter=";
int slen1 = sizeof(str1) - 1;
int slen2 = sizeof(str2) - 1;

for(idx=1; idx<ac; idx++) {
if(!strncmp(av[idx], str1, slen1)) {
tmp = strtol(av[idx]+slen1, NULL, 0);
if(tmp>0) {
*mproc = tmp;
}
}
if(!strncmp(av[idx], str2, slen2)) {
tmp = strtol(av[idx]+slen2, NULL, 0);
if(tmp>0) {
*rval = tmp;
}
}
}
}

int main(int ac, char *av[])
{
struct timeval tstart, tstop;
double delt;
int cnt;
int pipefd[2];
int rval = 1024*1024*5;
int mproc = 2;

signal(SIGUSR1, retme);
parrent_pid = getpid();

parse_cmdline(ac, av, &rval, &mproc);
printf("Running with iterations=%d and processes=%d\n", rval, mproc);

pipe(pipefd);

for(cnt=0; cnt<mproc; cnt++) {
pid_t pid = fork();

if(pid>0) {
printf("Launched %d\n", cnt);
} else if(pid==0) {
looper(pipefd);
return 0;
}
}

gettimeofday(&tstart, NULL);
write(pipefd[1], &rval, sizeof(rval));
while(!got_usr1) {
pause();
}
gettimeofday(&tstop, NULL);

delt = tstop.tv_sec - tstart.tv_sec;
delt += 1e-6*(tstop.tv_usec - tstart.tv_usec);
printf("Running %d inerations with %d processes took %.3f seconds\n",
rval, mproc, delt);

kill(-parrent_pid, SIGTERM);

return 0;
}

-- 
----------------------------------------------------------------------------
Jim Nance                                                 Avant! Corporation
(919) 941-6655    Do you have sweet iced tea?       jim_nance@avanticorp.com
                  No, but there's sugar on the table.

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/