Home | History | Annotate | Download | only in ffsb-6.0-rc2
      1 /*
      2  *   Copyright (c) International Business Machines Corp., 2001-2004
      3  *
      4  *   This program is free software;  you can redistribute it and/or modify
      5  *   it under the terms of the GNU General Public License as published by
      6  *   the Free Software Foundation; either version 2 of the License, or
      7  *   (at your option) any later version.
      8  *
      9  *   This program is distributed in the hope that it will be useful,
     10  *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
     11  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
     12  *   the GNU General Public License for more details.
     13  *
     14  *   You should have received a copy of the GNU General Public License
     15  *   along with this program;  if not, write to the Free Software
     16  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     17  */
     18 #include <pthread.h>
     19 #include <sys/time.h>
     20 #include <sys/times.h>
     21 #include <sys/types.h>
     22 #include <sys/wait.h>
     23 #include <unistd.h>
     24 #include <string.h>
     25 #include <stdio.h>
     26 #include <stdlib.h>
     27 #include <pthread.h>
     28 
     29 #include <assert.h>
     30 
     31 #include "config.h"
     32 
     33 #include "ffsb.h"
     34 #include "util.h"
     35 #include "parser.h"
     36 
     37 /* State information for the polling function below */
     38 struct ffsb_time_poll {
     39 	struct timeval starttime;
     40 	int wait_time;
     41 };
     42 
     43 /* This is the polling function used by the threadgroups to check
     44  * elapsed time, when it returns 1 they know it is time to stop
     45  */
     46 static int ffsb_poll_fn(void *ptr)
     47 {
     48 	struct ffsb_time_poll *data = (struct ffsb_time_poll *)ptr;
     49 	struct timeval curtime, difftime;
     50 	gettimeofday(&curtime, NULL);
     51 
     52 	timersub(&curtime, &data->starttime, &difftime);
     53 	if (difftime.tv_sec >= data->wait_time)
     54 		return 1;
     55 	return 0;
     56 }
     57 
     58 int main(int argc, char *argv[])
     59 {
     60 	int i;
     61 	ffsb_config_t fc;
     62 	ffsb_barrier_t thread_barrier, tg_barrier;
     63 	tg_run_params_t *params;
     64 	struct ffsb_time_poll pdata;
     65 	struct timeval starttime, endtime, difftime;
     66 	pthread_attr_t attr;
     67 	ffsb_op_results_t total_results;
     68 	double totaltime = 0.0f, usertime = 0.0f, systime = 0.0f;
     69 	struct rusage before_self, before_children, after_self, after_children;
     70 	pthread_t *fs_pts;	/* threads to do filesystem creates in parallel */
     71 	char *callout = NULL;
     72 
     73 	char ctime_start_buf[32];
     74 	char ctime_end_buf[32];
     75 
     76 	memset(&before_self, 0, sizeof(before_self));
     77 	memset(&before_children, 0, sizeof(before_children));
     78 	memset(&after_self, 0, sizeof(after_self));
     79 	memset(&after_children, 0, sizeof(after_children));
     80 
     81 	ffsb_unbuffer_stdout();
     82 
     83 	if (argc < 2) {
     84 		fprintf(stderr, "usage: %s <config file>\n", argv[0]);
     85 		exit(1);
     86 	}
     87 
     88 	/* VERSION comes from config.h (which is autogenerated by autoconf) */
     89 	printf("FFSB version %s started\n\n", VERSION);
     90 
     91 	ffsb_parse_newconfig(&fc, argv[1]);
     92 	pdata.wait_time = fc.time;
     93 
     94 	if (fc.time)
     95 		printf("benchmark time = %u\n", fc.time);
     96 	else
     97 		printf("Only creating the fileset, not running benchmark.\n");
     98 
     99 	pthread_attr_init(&attr);
    100 	pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
    101 
    102 	for (i = 0; i < fc.num_threadgroups; i++)
    103 		tg_print_config(&fc.groups[i]);
    104 
    105 	fs_pts = ffsb_malloc(sizeof(pthread_t) * fc.num_filesys);
    106 
    107 	gettimeofday(&starttime, NULL);
    108 	for (i = 0; i < fc.num_filesys; i++) {
    109 		fs_print_config(&fc.filesystems[i]);
    110 		pthread_create(fs_pts + i, &attr, construct_ffsb_fs,
    111 			       &fc.filesystems[i]);
    112 	}
    113 
    114 	fflush(stdout);
    115 	for (i = 0; i < fc.num_filesys; i++)
    116 		pthread_join(fs_pts[i], NULL);
    117 
    118 	gettimeofday(&endtime, NULL);
    119 	timersub(&endtime, &starttime, &difftime);
    120 	printf("fs setup took %ld secs\n", difftime.tv_sec);
    121 	free(fs_pts);
    122 
    123 	if (fc.time == 0) {
    124 		printf("Setup complete, exiting\n");
    125 		return 0;
    126 	}
    127 
    128 	params = ffsb_malloc(sizeof(tg_run_params_t) * fc.num_threadgroups);
    129 
    130 	init_ffsb_op_results(&total_results);
    131 	ffsb_barrier_init(&thread_barrier, fc.num_totalthreads);
    132 	ffsb_barrier_init(&tg_barrier, fc.num_threadgroups + 1);
    133 
    134 	ffsb_sync();
    135 
    136 	/* Execute the callout if any and wait for it to return */
    137 	callout = fc_get_callout(&fc);
    138 	if (callout) {
    139 		printf("executing callout: \n %s\n", callout);
    140 		if (ffsb_system(callout) < 0) {
    141 			perror("system");
    142 			exit(1);
    143 		}
    144 	}
    145 
    146 	/* Spawn all of the threadgroup master threads */
    147 	for (i = 0; i < fc.num_threadgroups; i++) {
    148 		params[i].tg = &fc.groups[i];
    149 		params[i].fc = &fc;
    150 		params[i].poll_fn = ffsb_poll_fn;
    151 		params[i].poll_data = &pdata;
    152 		params[i].wait_time = FFSB_TG_WAIT_TIME;
    153 		params[i].tg_barrier = &tg_barrier;
    154 		params[i].thread_barrier = &thread_barrier;
    155 
    156 		pthread_create(&params[i].pt, &attr, tg_run, &params[i]);
    157 	}
    158 
    159 	ffsb_getrusage(&before_self, &before_children);
    160 	gettimeofday(&pdata.starttime, NULL);
    161 
    162 	ffsb_barrier_wait(&tg_barrier);	/* sync with tg's to start */
    163 	printf("Starting Actual Benchmark At: %s\n",
    164 	       ctime_r(&pdata.starttime.tv_sec, ctime_start_buf));
    165 	fflush(stdout);
    166 
    167 	/* Wait for all of the threadgroup master threads to finish */
    168 	for (i = 0; i < fc.num_threadgroups; i++)
    169 		pthread_join(params[i].pt, NULL);
    170 
    171 	ffsb_sync();
    172 	gettimeofday(&endtime, NULL);
    173 	ffsb_getrusage(&after_self, &after_children);
    174 
    175 	printf("FFSB benchmark finished   at: %s\n",
    176 	       ctime_r(&endtime.tv_sec, ctime_end_buf));
    177 	printf("Results:\n");
    178 	fflush(stdout);
    179 
    180 	timersub(&endtime, &pdata.starttime, &difftime);
    181 
    182 	totaltime = tvtodouble(&difftime);
    183 
    184 	printf("Benchmark took %.2lf sec\n", totaltime);
    185 	printf("\n");
    186 
    187 	for (i = 0; i < fc.num_threadgroups; i++) {
    188 		struct ffsb_op_results tg_results;
    189 		ffsb_tg_t *tg = fc.groups + i;
    190 
    191 		init_ffsb_op_results(&tg_results);
    192 
    193 		/* Grab the individual tg results */
    194 		tg_collect_results(tg, &tg_results);
    195 
    196 		if (fc.num_threadgroups == 1)
    197 			printf("Total Results\n");
    198 		else
    199 			printf("ThreadGroup %d\n", i);
    200 
    201 		printf("===============\n");
    202 		print_results(&tg_results, totaltime);
    203 
    204 		if (tg_needs_stats(tg)) {
    205 			ffsb_statsd_t fsd;
    206 			tg_collect_stats(tg, &fsd);
    207 			ffsb_statsd_print(&fsd);
    208 		}
    209 		printf("\n");
    210 
    211 		/* Add the tg results to the total */
    212 		tg_collect_results(&fc.groups[i], &total_results);
    213 	}
    214 
    215 	if (fc.num_threadgroups > 1) {
    216 		printf("Total Results\n");
    217 		printf("===============\n");
    218 		print_results(&total_results, totaltime);
    219 	}
    220 #define USEC_PER_SEC ((double)(1000000.0f))
    221 
    222 	/* sum up self and children after */
    223 	usertime = (after_self.ru_utime.tv_sec +
    224 		    ((after_self.ru_utime.tv_usec) / USEC_PER_SEC)) +
    225 	    ((after_children.ru_utime.tv_sec +
    226 	      ((after_children.ru_utime.tv_usec) / USEC_PER_SEC)));
    227 
    228 	/* subtract away the before */
    229 	usertime -= (before_self.ru_utime.tv_sec +
    230 		     ((before_self.ru_utime.tv_usec) / USEC_PER_SEC)) +
    231 	    ((before_children.ru_utime.tv_sec +
    232 	      ((before_children.ru_utime.tv_usec) / USEC_PER_SEC)));
    233 
    234 	/* sum up self and children after */
    235 	systime = (after_self.ru_stime.tv_sec +
    236 		   ((after_self.ru_stime.tv_usec) / USEC_PER_SEC)) +
    237 	    ((after_children.ru_stime.tv_sec +
    238 	      ((after_children.ru_stime.tv_usec) / USEC_PER_SEC)));
    239 
    240 	/* subtract away the before */
    241 	systime -= (before_self.ru_stime.tv_sec +
    242 		    ((before_self.ru_stime.tv_usec) / USEC_PER_SEC)) +
    243 	    ((before_children.ru_stime.tv_sec +
    244 	      ((before_children.ru_stime.tv_usec) / USEC_PER_SEC)));
    245 
    246 	printf("\n\n");
    247 	printf("%.1lf%% User   Time\n", 100 * usertime / totaltime);
    248 	printf("%.1lf%% System Time\n", 100 * systime / totaltime);
    249 	printf("%.1f%% CPU Utilization\n", 100 * (usertime + systime) /
    250 	       totaltime);
    251 	free(params);
    252 	destroy_ffsb_config(&fc);
    253 
    254 	return 0;
    255 }
    256