#include <sys/sem.h>
struct options options = {
+ .backend = "fileio",
.timelimit = 600,
.loadfile = DATADIR "/client.txt",
.directory = ".",
.ea_enable = 0,
.clients_per_process = 1,
.server = "localhost",
+ .export = "/tmp",
+ .protocol = "tcp",
+ .run_once = 0,
+ .trunc_io = 0,
};
static struct timeval tv_start;
static struct timeval tv_end;
static int barrier=-1;
static double throughput;
+struct nb_operations *nb_ops;
static FILE *open_loadfile(void)
{
struct timeval tnow;
int num_active = 0;
int num_finished = 0;
-
(void)sig;
tnow = timeval_current();
for (i=0;i<nclients;i++) {
children[i].bytes_done_warmup = children[i].bytes;
children[i].worst_latency = 0;
+ memset(&children[i].ops, 0, sizeof(children[i].ops));
}
goto next;
}
alarm(PRINT_FREQ);
}
+
+static void show_one_latency(struct op *ops, struct op *ops_all)
+{
+ int i;
+ printf(" Operation Count AvgLat MaxLat\n");
+ printf(" --------------------------------------------------\n");
+ for (i=0;nb_ops->ops[i].name;i++) {
+ struct op *op1, *op_all;
+ op1 = &ops[i];
+ op_all = &ops_all[i];
+ if (op_all->count == 0) continue;
+ printf(" %-22s %7u %9.03f %9.03f\n",
+ nb_ops->ops[i].name, op1->count,
+ 1000*op1->total_time/op1->count,
+ op1->max_latency*1000);
+ }
+ printf("\n");
+}
+
+static void report_latencies(void)
+{
+ struct op sum[MAX_OPS];
+ int i, j;
+ struct op *op1, *op2;
+ struct child_struct *child;
+
+ memset(sum, 0, sizeof(sum));
+ for (i=0;nb_ops->ops[i].name;i++) {
+ op1 = &sum[i];
+ for (j=0;j<options.nprocs * options.clients_per_process;j++) {
+ child = &children[j];
+ op2 = &child->ops[i];
+ op1->count += op2->count;
+ op1->total_time += op2->total_time;
+ op1->max_latency = MAX(op1->max_latency, op2->max_latency);
+ }
+ }
+ show_one_latency(sum, sum);
+
+ if (!options.per_client_results) {
+ return;
+ }
+
+ printf("Per client results:\n");
+ for (i=0;i<options.nprocs * options.clients_per_process;i++) {
+ child = &children[i];
+ printf("Client %u did %u lines and %.0f bytes\n",
+ i, child->line, child->bytes - child->bytes_done_warmup);
+ show_one_latency(child->ops, sum);
+ }
+}
+
/* this creates the specified number of child processes and runs fn()
in all of them */
static void create_procs(int nprocs, void (*fn)(struct child_struct *, const char *))
setlinebuf(stdout);
for (j=0;j<options.clients_per_process;j++) {
- nb_setup(&children[i*options.clients_per_process + j]);
+ nb_ops->setup(&children[i*options.clients_per_process + j]);
}
sbuf.sem_op = 0;
sig_alarm(SIGALRM);
printf("\n");
-}
-
-static void show_usage(void)
-{
- printf("usage: dbench [OPTIONS] nprocs\n" \
- "usage: tbench [OPTIONS] nprocs <server>\n" \
- "options:\n" \
- " -v show version\n" \
- " -t timelimit run time in seconds (default 600)\n" \
- " -D directory base directory to run in\n" \
- " -c loadfile set location of the loadfile\n" \
- " -R target rate (MByte/sec)\n" \
- " -s synchronous file IO\n" \
- " -F fsync on write\n" \
- " -S synchronous directories (mkdir, unlink...)\n" \
- " -x enable EA support\n" \
- " -T options set socket options for tbench\n");
- exit(1);
+ report_latencies();
}
-static int process_opts(int argc, const char **argv)
+static void process_opts(int argc, const char **argv)
{
const char **extra_argv;
int extra_argc = 0;
struct poptOption popt_options[] = {
POPT_AUTOHELP
+ { "backend", 'B', POPT_ARG_STRING, &options.backend, 0,
+ "dbench backend (fileio, sockio, nfs)", "string" },
{ "timelimit", 't', POPT_ARG_INT, &options.timelimit, 0,
"timelimit", "integer" },
{ "loadfile", 'c', POPT_ARG_STRING, &options.loadfile, 0,
"fsync on write", NULL },
{ "xattr", 'x', POPT_ARG_NONE, &options.ea_enable, 0,
"use xattrs", NULL },
+ { "no-resolve", 0, POPT_ARG_NONE, &options.no_resolve, 0,
+ "disable name resolution simulation", NULL },
{ "clients-per-process", 0, POPT_ARG_INT, &options.clients_per_process, 0,
"number of clients per process", NULL },
+ { "trunc-io", 0, POPT_ARG_INT, &options.trunc_io, 0,
+ "truncate all io to this size", NULL },
+ { "one-byte-write-fix", 0, POPT_ARG_NONE, &options.one_byte_write_fix, 0,
+ "try to fix 1 byte writes", NULL },
+ { "stat-check", 0, POPT_ARG_NONE, &options.stat_check, 0,
+ "check for pointless calls with stat", NULL },
+ { "fake-io", 0, POPT_ARG_NONE, &options.fake_io, 0,
+ "fake up read/write calls", NULL },
+ { "skip-cleanup", 0, POPT_ARG_NONE, &options.skip_cleanup, 0,
+ "skip cleanup operations", NULL },
+ { "per-client-results", 0, POPT_ARG_NONE, &options.per_client_results, 0,
+ "show results per client", NULL },
+ { "server", 0, POPT_ARG_STRING, &options.server, 0,
+ "server", NULL },
+ { "export", 0, POPT_ARG_STRING, &options.export, 0,
+ "export", NULL },
+ { "protocol", 0, POPT_ARG_STRING, &options.protocol, 0,
+ "protocol", NULL },
+ { "run-once", 0, POPT_ARG_NONE, &options.run_once, 0,
+ "Stop once reaching the end of the loadfile", NULL},
+ { "scsi", 0, POPT_ARG_STRING, &options.scsi_dev, 0,
+ "scsi device", NULL },
+ { "warmup", 0, POPT_ARG_INT, &options.warmup, 0,
+ "How meny seconds of warmup to run", NULL },
POPT_TABLEEND
};
poptContext pc;
pc = poptGetContext(argv[0], argc, argv, popt_options, POPT_CONTEXT_KEEP_FIRST);
while ((opt = poptGetNextOpt(pc)) != -1) {
- switch (opt) {
- default:
- fprintf(stderr, "Invalid option %s: %s\n",
- poptBadOption(pc, 0), poptStrerror(opt));
+ if (strcmp(poptBadOption(pc, 0), "-h") == 0) {
+ poptPrintHelp(pc, stdout, 0);
exit(1);
}
+ fprintf(stderr, "Invalid option %s: %s\n",
+ poptBadOption(pc, 0), poptStrerror(opt));
+ exit(1);
}
/* setup the remaining options for the main program to use */
if (extra_argc >= 2) {
options.server = extra_argv[1];
}
-
- return 1;
}
printf("dbench version %s - Copyright Andrew Tridgell 1999-2004\n\n", VERSION);
- if (!process_opts(argc, argv))
- show_usage();
+ if (strstr(argv[0], "dbench")) {
+ options.backend = "fileio";
+ } else if (strstr(argv[0], "tbench")) {
+ options.backend = "sockio";
+ } else if (strstr(argv[0], "nfsbench")) {
+ options.backend = "nfs";
+ } else if (strstr(argv[0], "scsibench")) {
+ options.backend = "scsi";
+ }
+
+ process_opts(argc, argv);
+
+ if (strcmp(options.backend, "fileio") == 0) {
+ extern struct nb_operations fileio_ops;
+ nb_ops = &fileio_ops;
+ } else if (strcmp(options.backend, "sockio") == 0) {
+ extern struct nb_operations sockio_ops;
+ nb_ops = &sockio_ops;
+ } else if (strcmp(options.backend, "nfs") == 0) {
+ extern struct nb_operations nfs_ops;
+ nb_ops = &nfs_ops;
+#ifdef HAVE_LINUX_SCSI_SG
+ } else if (strcmp(options.backend, "scsi") == 0) {
+ extern struct nb_operations scsi_ops;
+ nb_ops = &scsi_ops;
+#endif /* HAVE_LINUX_SCSI_SG */
+ } else {
+ printf("Unknown backend '%s'\n", options.backend);
+ exit(1);
+ }
if (options.warmup == -1) {
options.warmup = options.timelimit / 5;