[net.sources] Measure data transmission rates through unix pipes followup to my net.unix-wizards article

mwherman@watcgl.UUCP (Michael W. Herman) (05/16/85)

Don't be concerned about the warning msgs produced by line 34 of
listener.c.  For some block sizes ("chunks"), an odd sized block
is transmitted to insure that a full 1M byte of data is transmitted
in the cases where 1M is not an integral multiple of the block size.

The timing statistics are written to *stdout*.  *timesPrint* insures
that the talker and listener don't write to *stdout* at the same
time.  Error msgs appear on *stderr*.  Enjoy.

Michael Herman
Computer Graphics Laboratory
Department of Computer Science
University of Waterloo
Waterloo, Ontario, Canada  N2L 3G1

UUCP:   {allegra,ihnp4,watmath}!watcgl!mwherman
-or-    {cbosgd,clyde,decvax,linus,tektronix,utcsrgv}!watmath!watcgl!mwherman
CSNET:  mwherman%watcgl@waterloo.CSNET
ARPA:   mwherman%watcgl%waterloo.CSNET@csnet-relay.ARPA  

---- Tear here --------------------------------------------------------------
# This is a shell archive.  Remove anything before this line, then
# unpack it by saving it in a file and typing "sh file".  (Files
# unpacked will be owned by you and have default permissions.)
#
# This archive contains:
# Makefile hdr.h listener.c stats.example talker.c timesPrint.c

echo x - Makefile
cat > "Makefile" << '//E*O*F Makefile//'
CFLAGS   = 
LIBS     = timesPrint.o

all:	talker listener

talker: talker.c hdr.h timesPrint.o
	cc ${CFLAGS} $@.c -o $@ ${LIBS}

listener: listener.c hdr.h timesPrint.o
	cc ${CFLAGS} $@.c -o $@ ${LIBS}

timesPrint.o:	hdr.h

run:
	talker >>stats
//E*O*F Makefile//

echo x - hdr.h
cat > "hdr.h" << '//E*O*F hdr.h//'
/* imported definitions */
#include <errno.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/times.h>
#include <sys/time.h>

/* constants */
#define NO_BYTES	(1024*1024)
#define MIN_CHUNK       128
#define MAX_CHUNK       4096

#define MAX_ERRORS      5

/* global variables */
char buf[MAX_CHUNK];
struct timeval start_time;
struct timeval end_time;
struct timezone time_zone;

/* function declarations */
void timesPrint();

/* dummy error handling macros */
#define ErrorMsg(File,Line,Format,Valuea,Valueb) \
		fprintf(stderr, "%s, line %d:", File, Line); \
		fprintf(stderr, Format, Valuea, Valueb); \
		fprintf(stderr, "\n" ); \
		fflush (stderr);

#define ErrorSystem(File,Line,Fileno,Rc) \
	    { \
		extern int errno; \
		extern char* sys_errlist[]; \
	        \
		if (Rc < 0) { \
		    ErrorMsg(File, Line, \
	    "negative return code (%d) returned by system call for fd %d", \
			     Rc, Fileno); \
		    ErrorMsg(File, Line, \
			     "errno was %d.  corresponding msg is '%s'", \
			     errno, sys_errlist[errno]); \
		    } \
	     }
/* 
 *  Note: I have a real error handling library but it is too difficult to
 *        distribute for something as small as this.  mwherman@watcgl
 */
//E*O*F hdr.h//

echo x - listener.c
cat > "listener.c" << '//E*O*F listener.c//'
#include "hdr.h"

main(argc, argv) 
int argc;
char * argv[];
{
    FILE * earpiece = stdin;
    int    chunk;
    int    rc;
    int    no_bytes;
    int    check_value;
    int    no_errors;

    no_errors = 0;

    rc = read( fileno(earpiece), &chunk, sizeof(chunk) );
    ErrorSystem( __FILE__, __LINE__, fileno(earpiece), rc );

#   ifdef
       fprintf( stderr, "%s, line %d:chunk %d\n", __FILE__, __LINE__, chunk );
       fflush( stderr );
#      endif

    check_value = chunk;
    (void) gettimeofday( &start_time, &time_zone );
    for (no_bytes = 0; ;no_bytes += rc) {
        rc = read( fileno(earpiece), buf, chunk );
        ErrorSystem( __FILE__, __LINE__, fileno(earpiece), rc );

	if (rc == 0) 
	    break;

	if ((rc != chunk) && (no_errors < MAX_ERRORS)) {
	    ErrorMsg( __FILE__, __LINE__, 
	              "warning:partial chunk %d != chunk %d", rc, chunk );
	    no_errors++;
	    }

#       ifdef DEBUG
	    if (no_bytes % check_value == 0) {
    	        fprintf( stderr, "%s, line %d:chunk, no_bytes %d, %d\n", 
			         __FILE__, __LINE__, chunk, no_bytes );
    	        fflush( stderr );
		check_value *= 4;
	        }
#	    endif
	}
    (void) gettimeofday( &end_time, &time_zone );

#   ifdef DEBUG
        fprintf( stderr, "%-8s:no_bytes %d\n", "listener", no_bytes );
#       endif

    (void) timesPrint( argv[0], chunk, start_time, end_time );
    fflush( stderr );
}
//E*O*F listener.c//

echo x - stats.example
cat > "stats.example" << '//E*O*F stats.example//'
talker  :chunk 4096	sec 2.860000
listener:chunk 4096	sec 2.700000
talker  :chunk 3968	sec 4.100000
listener:chunk 3968	sec 4.010000
talker  :chunk 3840	sec 4.040000
listener:chunk 3840	sec 3.850000
talker  :chunk 3712	sec 4.220000
listener:chunk 3712	sec 3.970000
talker  :chunk 3584	sec 6.130000
listener:chunk 3584	sec 5.930000
talker  :chunk 3456	sec 6.030000
listener:chunk 3456	sec 5.870000
talker  :chunk 3328	sec 6.920000
listener:chunk 3328	sec 6.660000
talker  :chunk 3200	sec 6.190000
listener:chunk 3200	sec 5.970000
talker  :chunk 3072	sec 3.190000
listener:chunk 3072	sec 3.010000
talker  :chunk 2944	sec 5.830000
listener:chunk 2944	sec 5.640000
talker  :chunk 2816	sec 7.410000
listener:chunk 2816	sec 7.170000
talker  :chunk 2688	sec 4.300000
listener:chunk 2688	sec 4.130000
talker  :chunk 2560	sec 4.750000
listener:chunk 2560	sec 4.420000
talker  :chunk 2432	sec 7.590000
listener:chunk 2432	sec 7.380000
talker  :chunk 2304	sec 5.550000
listener:chunk 2304	sec 5.360000
talker  :chunk 2176	sec 4.200000
listener:chunk 2176	sec 3.970000
talker  :chunk 2048	sec 3.430000
listener:chunk 2048	sec 3.280000
talker  :chunk 1920	sec 5.430000
listener:chunk 1920	sec 5.350000
talker  :chunk 1792	sec 8.240000
listener:chunk 1792	sec 8.000000
talker  :chunk 1664	sec 11.410000
listener:chunk 1664	sec 11.320000
talker  :chunk 1536	sec 7.760000
listener:chunk 1536	sec 7.540000
talker  :chunk 1408	sec 7.380000
listener:chunk 1408	sec 7.050000
talker  :chunk 1280	sec 8.070000
listener:chunk 1280	sec 7.870000
talker  :chunk 1152	sec 8.760000
listener:chunk 1152	sec 8.570000
talker  :chunk 1024	sec 7.390000
listener:chunk 1024	sec 7.220000
talker  :chunk 896	sec 13.210000
listener:chunk 896	sec 13.320000
talker  :chunk 768	sec 14.360000
listener:chunk 768	sec 14.160000
talker  :chunk 640	sec 18.630000
listener:chunk 640	sec 18.410000
talker  :chunk 512	sec 15.470000
listener:chunk 512	sec 14.820000
talker  :chunk 384	sec 13.110000
listener:chunk 384	sec 12.890000
talker  :chunk 256	sec 17.840000
listener:chunk 256	sec 17.640000
talker  :chunk 128	sec 35.080000
listener:chunk 128	sec 34.850000
//E*O*F stats.example//

echo x - talker.c
cat > "talker.c" << '//E*O*F talker.c//'
#include <stdio.h>
#include "hdr.h"
char    buf[MAX_CHUNK];

main(argc, argv) 
int argc;
char * argv[];
{
    FILE * mouthpiece;
    int    chunk;
    int    rc;
    int    no_bytes;

    for (no_bytes = 0; no_bytes < MAX_CHUNK; no_bytes++)
	buf[no_bytes] = -1;

    for (chunk = MAX_CHUNK; chunk >= MIN_CHUNK; chunk -= 128) {
        mouthpiece = (FILE *) popen( "listener", "w" );

#       ifdef DEBUG
	    fprintf( stderr, "%s, line %d:mouthpiece %d\n", 
				__FILE__, __LINE__, mouthpiece );
	    fflush( stderr );
	    fprintf( stderr, "%s, line %d:fileno(mouthpiece) %d\n", 
				__FILE__, __LINE__, fileno(mouthpiece) );
	    fflush( stderr );
#           endif

	if (mouthpiece == (FILE *) NULL)
	    ErrorSystem( __FILE__, __LINE__, -1, -1 );

	rc = write( fileno(mouthpiece), &chunk, sizeof(chunk) );
	ErrorSystem( __FILE__, __LINE__, fileno(mouthpiece), rc );

	(void) gettimeofday( &start_time, &time_zone );
	for (no_bytes = 0; no_bytes < (NO_BYTES-chunk); no_bytes += chunk) {
#           ifdef DEBUG
            if (no_bytes > 1000*1000)
	        fprintf( stderr, "%s, line %d:no_bytes %d	NO_BYTES %d\n", 
				 __FILE__, __LINE__, no_bytes, NO_BYTES );
#               endif

	    rc = write( fileno(mouthpiece), buf, chunk );
	    ErrorSystem( __FILE__, __LINE__, fileno(mouthpiece), rc );
	    }
	if (no_bytes < NO_BYTES) {
#           ifdef DEBUG
	        fprintf( stderr, "%s, line %d:NO_BYTES-no_bytes %d\n", 
				 __FILE__, __LINE__, NO_BYTES-no_bytes );
#               endif

	    rc = write( fileno(mouthpiece), buf, NO_BYTES-no_bytes );
	    ErrorSystem( __FILE__, __LINE__, fileno(mouthpiece), rc );

	    no_bytes += (NO_BYTES-no_bytes);
	    }
	(void) gettimeofday( &end_time, &time_zone );

#       ifdef DEBUG
            fprintf( stderr, "%-8s:no_bytes %d\n", "talker", no_bytes );
#           endif

        (void) timesPrint( "talker", chunk, start_time, end_time );
	rc = pclose( mouthpiece );
	ErrorSystem( __FILE__, __LINE__, fileno(mouthpiece), rc );
	}
}
//E*O*F talker.c//

echo x - timesPrint.c
cat > "timesPrint.c" << '//E*O*F timesPrint.c//'
#include "hdr.h"

void
timesPrint( routine, chunk, start_time, end_time )
char * routine;
int chunk;
struct timeval start_time;
struct timeval end_time;
{
    int rc;
    extern int errno;

    while( (rc=symlink("/dev/null","timesPrint.lock")) != 0) {
	if (errno != EEXIST) ErrorSystem( __FILE__, __LINE__, -1, rc );
	}

    printf( "%-8s:chunk %d	sec %f\n",
		     routine, chunk,
		     (float)(end_time.tv_sec - start_time.tv_sec) + 
		     (float)(end_time.tv_usec - start_time.tv_usec) * 1e-6 );
    fflush( stdout );

    rc = unlink("timesPrint.lock");
    ErrorSystem( __FILE__, __LINE__, -1, rc );
}
//E*O*F timesPrint.c//

exit 0