2 Copyright (C) by Andrew Tridgell <tridge@samba.org> 1999, 2001
3 Copyright (C) 2001 by Martin Pool <mbp@samba.org>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 /* TODO: We could try allowing for different flavours of synchronous
21 operation: data sync and so on. Linux apparently doesn't make any
22 distinction, however, and for practical purposes it probably
23 doesn't matter. On NFSv4 it might be interesting, since the client
24 can choose what kind it wants for each OPEN operation. */
29 int sync_open = 0, do_fsync = 0, sync_dirs = 0;
30 char *tcp_options = TCP_OPTIONS;
31 static int timelimit = 600, warmup;
32 static const char *directory = ".";
33 static char *loadfile = DATADIR "/client.txt";
34 static struct timeval tv_start;
35 static struct timeval tv_end;
36 static int barrier=-1;
43 static FILE *open_loadfile(void)
47 if ((f = fopen(loadfile, "rt")) != NULL)
51 "dbench: error opening '%s': %s\n", loadfile,
58 static struct child_struct *children;
60 static void sem_cleanup() {
62 semctl(barrier,0,IPC_RMID);
65 static void sig_alarm(int sig)
67 double total_bytes = 0;
70 int nprocs = children[0].nprocs;
73 static int in_cleanup;
79 tnow = timeval_current();
81 for (i=0;i<nprocs;i++) {
82 total_bytes += children[i].bytes - children[i].bytes_done_warmup;
83 if (children[i].bytes == 0) {
86 total_lines += children[i].line;
89 t = timeval_elapsed(&tv_start);
91 if (!in_warmup && warmup>0 && t > warmup) {
94 for (i=0;i<nprocs;i++) {
95 children[i].bytes_done_warmup = children[i].bytes;
101 } else if (!in_warmup && !in_cleanup && t > timelimit) {
102 for (i=0;i<nprocs;i++) {
103 children[i].done = 1;
113 for (i=0;i<nprocs;i++) {
114 latency = MAX(children[i].max_latency, latency);
115 latency = MAX(latency, timeval_elapsed2(&children[i].lasttime, &tnow));
116 children[i].max_latency = 0;
120 printf("%4d %8d %7.2f MB/sec warmup %3.0f sec latency %.03f ms \n",
121 nprocs, total_lines/nprocs,
122 1.0e-6 * total_bytes / t, t, latency*1000);
123 } else if (in_cleanup) {
124 printf("%4d %8d %7.2f MB/sec cleanup %3.0f sec latency %.03f ms\n",
125 nprocs, total_lines/nprocs,
126 1.0e-6 * total_bytes / t, t, latency*1000);
128 printf("%4d %8d %7.2f MB/sec execute %3.0f sec latency %.03f ms\n",
129 nprocs, total_lines/nprocs,
130 1.0e-6 * total_bytes / t, t, latency*1000);
135 signal(SIGALRM, sig_alarm);
139 /* this creates the specified number of child processes and runs fn()
141 static void create_procs(int nprocs, void (*fn)(struct child_struct *, const char *))
150 load = open_loadfile();
157 "create %d procs? you must be kidding.\n",
162 children = shm_setup(sizeof(struct child_struct)*nprocs);
164 printf("Failed to setup shared memory\n");
168 memset(children, 0, sizeof(*children)*nprocs);
170 for (i=0;i<nprocs;i++) {
172 children[i].nprocs = nprocs;
173 children[i].cleanup = 0;
174 children[i].directory = directory;
175 children[i].starttime = timeval_current();
178 if (atexit(sem_cleanup) != 0) {
179 printf("can't register cleanup function on exit\n");
183 if ( !(barrier = semget(IPC_PRIVATE,1,IPC_CREAT | S_IRUSR | S_IWUSR)) ) {
184 printf("failed to create barrier semaphore \n");
186 sbuf.sem_flg = SEM_UNDO;
188 if (semop(barrier, &sbuf, 1) == -1) {
189 printf("failed to initialize the barrier semaphore\n");
194 for (i=0;i<nprocs;i++) {
197 nb_setup(&children[i]);
200 if (semop(barrier, &sbuf, 1) == -1) {
201 printf("failed to use the barrier semaphore in child %d\n",getpid());
205 semctl(barrier,0,IPC_RMID);
207 fn(&children[i], loadfile);
213 tv = timeval_current();
215 synccount = semctl(barrier,0,GETZCNT);
216 t = timeval_elapsed(&tv);
217 printf("%d of %d clients prepared for launch %3.0f sec\n", synccount, nprocs, t);
218 if (synccount == nprocs) break;
220 } while (timeval_elapsed(&tv) < 30);
222 if (synccount != nprocs) {
223 printf("FAILED TO START %d CLIENTS (started %d)\n", nprocs, synccount);
227 printf("releasing clients\n");
228 tv_start = timeval_current();
230 if (semop(barrier, &sbuf, 1) == -1) {
231 printf("failed to release barrier\n");
235 semctl(barrier,0,IPC_RMID);
237 signal(SIGALRM, sig_alarm);
240 for (i=0;i<nprocs;) {
241 if (waitpid(0, &status, 0) == -1) continue;
242 if (WEXITSTATUS(status) != 0) {
243 printf("Child failed with status %d\n",
244 WEXITSTATUS(status));
257 static void show_usage(void)
259 printf("usage: dbench [OPTIONS] nprocs\n" \
260 "usage: tbench [OPTIONS] nprocs <server>\n" \
262 " -v show version\n" \
263 " -t timelimit run time in seconds (default 600)\n" \
264 " -D directory base directory to run in\n" \
265 " -c loadfile set location of the loadfile\n" \
266 " -R target rate (MByte/sec)\n" \
267 " -s synchronous file IO\n" \
268 " -F fsync on write\n" \
269 " -S synchronous directories (mkdir, unlink...)\n" \
270 " -x enable EA support\n" \
271 " -T options set socket options for tbench\n");
277 static int process_opts(int argc, char **argv,
281 extern int sync_open;
286 while ((c = getopt(argc, argv, "vc:sST:t:xD:R:F")) != -1)
301 tcp_options = optarg;
304 timelimit = atoi(optarg);
313 targetrate = strtod(optarg, NULL);
320 printf("EA suppport not compiled in\n");
325 if (isprint (optopt))
326 fprintf (stderr, "Unknown option `-%c'.\n", optopt);
329 "Unknown option character `\\x%x'.\n",
339 *nprocs = atoi(argv[optind++]);
342 server = argv[optind++];
349 int main(int argc, char *argv[])
352 double total_bytes = 0;
356 printf("dbench version %s - Copyright Andrew Tridgell 1999-2004\n\n", VERSION);
358 if (!process_opts(argc, argv, &nprocs))
361 warmup = timelimit / 5;
363 printf("Running for %d seconds with load '%s' and minimum warmup %d secs\n",
364 timelimit, loadfile, warmup);
366 create_procs(nprocs, child_run);
368 for (i=0;i<nprocs;i++) {
369 total_bytes += children[i].bytes - children[i].bytes_done_warmup;
372 t = timeval_elapsed2(&tv_start, &tv_end);
374 printf("Throughput %g MB/sec%s%s %d procs\n",
375 1.0e-6 * total_bytes / t,
376 sync_open ? " (sync open)" : "",
377 sync_dirs ? " (sync dirs)" : "", nprocs);