• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
ffsb_poll_fn(void * ptr)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 
main(int argc,char * argv[])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