Home | History | Annotate | Download | only in bench
      1 /*
      2  *
      3  * sched-pipe.c
      4  *
      5  * pipe: Benchmark for pipe()
      6  *
      7  * Based on pipe-test-1m.c by Ingo Molnar <mingo (at) redhat.com>
      8  *  http://people.redhat.com/mingo/cfs-scheduler/tools/pipe-test-1m.c
      9  * Ported to perf by Hitoshi Mitake <mitake (at) dcl.info.waseda.ac.jp>
     10  *
     11  */
     12 
     13 #include "../perf.h"
     14 #include "../util/util.h"
     15 #include "../util/parse-options.h"
     16 #include "../builtin.h"
     17 #include "bench.h"
     18 
     19 #include <unistd.h>
     20 #include <stdio.h>
     21 #include <stdlib.h>
     22 #include <signal.h>
     23 #include <sys/wait.h>
     24 #include <linux/unistd.h>
     25 #include <string.h>
     26 #include <errno.h>
     27 #include <assert.h>
     28 #include <sys/time.h>
     29 #include <sys/types.h>
     30 
     31 #define LOOPS_DEFAULT 1000000
     32 static int loops = LOOPS_DEFAULT;
     33 
     34 static const struct option options[] = {
     35 	OPT_INTEGER('l', "loop", &loops,
     36 		    "Specify number of loops"),
     37 	OPT_END()
     38 };
     39 
     40 static const char * const bench_sched_pipe_usage[] = {
     41 	"perf bench sched pipe <options>",
     42 	NULL
     43 };
     44 
     45 int bench_sched_pipe(int argc, const char **argv,
     46 		     const char *prefix __maybe_unused)
     47 {
     48 	int pipe_1[2], pipe_2[2];
     49 	int m = 0, i;
     50 	struct timeval start, stop, diff;
     51 	unsigned long long result_usec = 0;
     52 
     53 	/*
     54 	 * why does "ret" exist?
     55 	 * discarding returned value of read(), write()
     56 	 * causes error in building environment for perf
     57 	 */
     58 	int __maybe_unused ret, wait_stat;
     59 	pid_t pid, retpid __maybe_unused;
     60 
     61 	argc = parse_options(argc, argv, options,
     62 			     bench_sched_pipe_usage, 0);
     63 
     64 	BUG_ON(pipe(pipe_1));
     65 	BUG_ON(pipe(pipe_2));
     66 
     67 	pid = fork();
     68 	assert(pid >= 0);
     69 
     70 	gettimeofday(&start, NULL);
     71 
     72 	if (!pid) {
     73 		for (i = 0; i < loops; i++) {
     74 			ret = read(pipe_1[0], &m, sizeof(int));
     75 			ret = write(pipe_2[1], &m, sizeof(int));
     76 		}
     77 	} else {
     78 		for (i = 0; i < loops; i++) {
     79 			ret = write(pipe_1[1], &m, sizeof(int));
     80 			ret = read(pipe_2[0], &m, sizeof(int));
     81 		}
     82 	}
     83 
     84 	gettimeofday(&stop, NULL);
     85 	timersub(&stop, &start, &diff);
     86 
     87 	if (pid) {
     88 		retpid = waitpid(pid, &wait_stat, 0);
     89 		assert((retpid == pid) && WIFEXITED(wait_stat));
     90 	} else {
     91 		exit(0);
     92 	}
     93 
     94 	switch (bench_format) {
     95 	case BENCH_FORMAT_DEFAULT:
     96 		printf("# Executed %d pipe operations between two tasks\n\n",
     97 			loops);
     98 
     99 		result_usec = diff.tv_sec * 1000000;
    100 		result_usec += diff.tv_usec;
    101 
    102 		printf(" %14s: %lu.%03lu [sec]\n\n", "Total time",
    103 		       diff.tv_sec,
    104 		       (unsigned long) (diff.tv_usec/1000));
    105 
    106 		printf(" %14lf usecs/op\n",
    107 		       (double)result_usec / (double)loops);
    108 		printf(" %14d ops/sec\n",
    109 		       (int)((double)loops /
    110 			     ((double)result_usec / (double)1000000)));
    111 		break;
    112 
    113 	case BENCH_FORMAT_SIMPLE:
    114 		printf("%lu.%03lu\n",
    115 		       diff.tv_sec,
    116 		       (unsigned long) (diff.tv_usec / 1000));
    117 		break;
    118 
    119 	default:
    120 		/* reaching here is something disaster */
    121 		fprintf(stderr, "Unknown format:%d\n", bench_format);
    122 		exit(1);
    123 		break;
    124 	}
    125 
    126 	return 0;
    127 }
    128