summaryrefslogtreecommitdiffstats
path: root/extras/benchmarking/glfs-bm.c
diff options
context:
space:
mode:
Diffstat (limited to 'extras/benchmarking/glfs-bm.c')
-rw-r--r--extras/benchmarking/glfs-bm.c619
1 files changed, 619 insertions, 0 deletions
diff --git a/extras/benchmarking/glfs-bm.c b/extras/benchmarking/glfs-bm.c
new file mode 100644
index 00000000000..f5e63ae8014
--- /dev/null
+++ b/extras/benchmarking/glfs-bm.c
@@ -0,0 +1,619 @@
+/*
+ Copyright (c) 2008 Z RESEARCH, Inc. <http://www.zresearch.com>
+ This file is part of GlusterFS.
+ GlusterFS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3 of the License,
+ or (at your option) any later version.
+
+ GlusterFS is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <http://www.gnu.org/licenses/>.
+*/
+
+#define _GNU_SOURCE
+#define __USE_FILE_OFFSET64
+#define _FILE_OFFSET_BITS 64
+
+#include <stdio.h>
+#include <argp.h>
+#include <libglusterfsclient.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/xattr.h>
+#include <string.h>
+#include <libgen.h>
+#include <errno.h>
+#include <sys/time.h>
+
+struct state {
+ char need_op_write:1;
+ char need_op_read:1;
+
+ char need_iface_fileio:1;
+ char need_iface_xattr:1;
+
+ char need_mode_posix:1;
+ char need_mode_libglusterfsclient:1;
+
+ char prefix[512];
+ long int count;
+
+ size_t block_size;
+
+ char *specfile;
+ void *libglusterfsclient_context;
+
+ long int io_size;
+};
+
+
+#define MEASURE(func, arg) measure (func, #func, arg)
+
+
+void
+tv_difference (struct timeval *tv_stop,
+ struct timeval *tv_start,
+ struct timeval *tv_diff)
+{
+ if (tv_stop->tv_usec < tv_start->tv_usec) {
+ tv_diff->tv_usec = (tv_stop->tv_usec + 1000000) - tv_start->tv_usec;
+ tv_diff->tv_sec = (tv_stop->tv_sec - 1 - tv_start->tv_sec);
+ } else {
+ tv_diff->tv_usec = tv_stop->tv_usec - tv_start->tv_usec;
+ tv_diff->tv_sec = tv_stop->tv_sec - tv_start->tv_sec;
+ }
+}
+
+
+void
+measure (int (*func)(struct state *state),
+ char *func_name, struct state *state)
+{
+ struct timeval tv_start, tv_stop, tv_diff;
+ state->io_size = 0;
+ long int count;
+
+ gettimeofday (&tv_start, NULL);
+ count = func (state);
+ gettimeofday (&tv_stop, NULL);
+
+ tv_difference (&tv_stop, &tv_start, &tv_diff);
+
+ fprintf (stdout, "%s: count=%ld, size=%ld, time=%ld:%ld\n",
+ func_name, count, state->io_size,
+ tv_diff.tv_sec, tv_diff.tv_usec);
+}
+
+
+static error_t
+parse_opts (int key, char *arg,
+ struct argp_state *_state)
+{
+ struct state *state = _state->input;
+
+ switch (key)
+ {
+ case 'o':
+ if (strcasecmp (arg, "read") == 0) {
+ state->need_op_write = 0;
+ state->need_op_read = 1;
+ } else if (strcasecmp (arg, "write") == 0) {
+ state->need_op_write = 1;
+ state->need_op_read = 0;
+ } else if (strcasecmp (arg, "both") == 0) {
+ state->need_op_write = 1;
+ state->need_op_read = 1;
+ } else {
+ fprintf (stderr, "unknown op: %s\n", arg);
+ return -1;
+ }
+ break;
+ case 'i':
+ if (strcasecmp (arg, "fileio") == 0) {
+ state->need_iface_fileio = 1;
+ state->need_iface_xattr = 0;
+ } else if (strcasecmp (arg, "xattr") == 0) {
+ state->need_iface_fileio = 0;
+ state->need_iface_xattr = 1;
+ } else if (strcasecmp (arg, "both") == 0) {
+ state->need_iface_fileio = 1;
+ state->need_iface_xattr = 1;
+ } else {
+ fprintf (stderr, "unknown interface: %s\n", arg);
+ return -1;
+ }
+ break;
+ case 'm':
+ if (strcasecmp (arg, "posix") == 0) {
+ state->need_mode_posix = 1;
+ state->need_mode_libglusterfsclient = 0;
+ } else if (strcasecmp (arg, "libglusterfsclient") == 0) {
+ state->need_mode_posix = 0;
+ state->need_mode_libglusterfsclient = 1;
+ } else if (strcasecmp (arg, "both") == 0) {
+ state->need_mode_posix = 1;
+ state->need_mode_libglusterfsclient = 1;
+ } else {
+ fprintf (stderr, "unknown mode: %s\n", arg);
+ return -1;
+ }
+ break;
+ case 'b':
+ {
+ size_t block_size = atoi (arg);
+ if (!block_size) {
+ fprintf (stderr, "incorrect size: %s\n", arg);
+ return -1;
+ }
+ state->block_size = block_size;
+ }
+ break;
+ case 's':
+ state->specfile = strdup (arg);
+ break;
+ case 'p':
+ fprintf (stderr, "using prefix: %s\n", arg);
+ strncpy (state->prefix, arg, 512);
+ break;
+ case 'c':
+ {
+ long count = atol (arg);
+ if (!count) {
+ fprintf (stderr, "incorrect count: %s\n", arg);
+ return -1;
+ }
+ state->count = count;
+ }
+ break;
+ case ARGP_KEY_NO_ARGS:
+ break;
+ case ARGP_KEY_ARG:
+ break;
+ }
+
+ return 0;
+}
+
+int
+do_mode_posix_iface_fileio_write (struct state *state)
+{
+ long int i;
+ int ret = -1;
+ char block[state->block_size];
+
+ for (i=0; i<state->count; i++) {
+ int fd = -1;
+ char filename[512];
+
+ sprintf (filename, "%s.%06ld", state->prefix, i);
+
+ fd = open (filename, O_CREAT|O_WRONLY, 00600);
+ if (fd == -1) {
+ fprintf (stderr, "open(%s) => %s\n", filename, strerror (errno));
+ break;
+ }
+ ret = write (fd, block, state->block_size);
+ if (ret != state->block_size) {
+ fprintf (stderr, "write (%s) => %d/%s\n", filename, ret,
+ strerror (errno));
+ close (fd);
+ break;
+ }
+ close (fd);
+ state->io_size += ret;
+ }
+
+ return i;
+}
+
+
+int
+do_mode_posix_iface_fileio_read (struct state *state)
+{
+ long int i;
+ int ret = -1;
+ char block[state->block_size];
+
+ for (i=0; i<state->count; i++) {
+ int fd = -1;
+ char filename[512];
+
+ sprintf (filename, "%s.%06ld", state->prefix, i);
+
+ fd = open (filename, O_RDONLY);
+ if (fd == -1) {
+ fprintf (stderr, "open(%s) => %s\n", filename, strerror (errno));
+ break;
+ }
+ ret = read (fd, block, state->block_size);
+ if (ret == -1) {
+ fprintf (stderr, "read(%s) => %d/%s\n", filename, ret, strerror (errno));
+ close (fd);
+ break;
+ }
+ close (fd);
+ state->io_size += ret;
+ }
+
+ return i;
+}
+
+
+int
+do_mode_posix_iface_fileio (struct state *state)
+{
+ if (state->need_op_write)
+ MEASURE (do_mode_posix_iface_fileio_write, state);
+
+ if (state->need_op_read)
+ MEASURE (do_mode_posix_iface_fileio_read, state);
+
+ return 0;
+}
+
+
+int
+do_mode_posix_iface_xattr_write (struct state *state)
+{
+ long int i;
+ int ret = -1;
+ char block[state->block_size];
+ char *dname = NULL, *dirc = NULL;
+ char *bname = NULL, *basec = NULL;
+
+ dirc = strdup (state->prefix);
+ basec = strdup (state->prefix);
+ dname = dirname (dirc);
+ bname = basename (basec);
+
+ for (i=0; i<state->count; i++) {
+ char key[512];
+
+ sprintf (key, "glusterfs.file.%s.%06ld", bname, i);
+
+ ret = lsetxattr (dname, key, block, state->block_size, 0);
+
+ if (ret != 0) {
+ fprintf (stderr, "lsetxattr (%s, %s, %p) => %s\n",
+ dname, key, block, strerror (errno));
+ break;
+ }
+ state->io_size += state->block_size;
+ }
+
+ free (dirc);
+ free (basec);
+
+ return i;
+}
+
+
+int
+do_mode_posix_iface_xattr_read (struct state *state)
+{
+ long int i;
+ int ret = -1;
+ char block[state->block_size];
+ char *dname = NULL, *dirc = NULL;
+ char *bname = NULL, *basec = NULL;
+
+ dirc = strdup (state->prefix);
+ basec = strdup (state->prefix);
+ dname = dirname (dirc);
+ bname = basename (basec);
+
+ for (i=0; i<state->count; i++) {
+ char key[512];
+
+ sprintf (key, "glusterfs.file.%s.%06ld", bname, i);
+
+ ret = lgetxattr (dname, key, block, state->block_size);
+
+ if (ret < 0) {
+ fprintf (stderr, "lgetxattr (%s, %s, %p) => %s\n",
+ dname, key, block, strerror (errno));
+ break;
+ }
+ state->io_size += ret;
+ }
+
+ return i;
+}
+
+
+int
+do_mode_posix_iface_xattr (struct state *state)
+{
+ if (state->need_op_write)
+ MEASURE (do_mode_posix_iface_xattr_write, state);
+
+ if (state->need_op_read)
+ MEASURE (do_mode_posix_iface_xattr_read, state);
+
+ return 0;
+}
+
+
+int
+do_mode_libglusterfsclient_iface_fileio_write (struct state *state)
+{
+ long int i;
+ int ret = -1;
+ char block[state->block_size];
+
+ for (i=0; i<state->count; i++) {
+ long fd = 0;
+ char filename[512];
+
+ sprintf (filename, "/%s.%06ld", state->prefix, i);
+
+ fd = glusterfs_open (state->libglusterfsclient_context,
+ filename, O_CREAT|O_WRONLY, 0);
+
+ if (fd == 0) {
+ fprintf (stderr, "open(%s) => %s\n", filename, strerror (errno));
+ break;
+ }
+ ret = glusterfs_write (fd, block, state->block_size);
+ if (ret == -1) {
+ fprintf (stderr, "glusterfs_write(%s) => %s\n", filename, strerror (errno));
+ glusterfs_close (fd);
+ break;
+ }
+ glusterfs_close (fd);
+ state->io_size += ret;
+ }
+
+ return i;
+}
+
+
+int
+do_mode_libglusterfsclient_iface_fileio_read (struct state *state)
+{
+ long int i;
+ int ret = -1;
+ char block[state->block_size];
+
+ for (i=0; i<state->count; i++) {
+ long fd = 0;
+ char filename[512];
+
+ sprintf (filename, "/%s.%06ld", state->prefix, i);
+
+ fd = glusterfs_open (state->libglusterfsclient_context,
+ filename, O_RDONLY, 0);
+
+ if (fd == 0) {
+ fprintf (stderr, "glusterfs_open(%s) => %s\n", filename, strerror (errno));
+ break;
+ }
+ ret = glusterfs_read (fd, block, state->block_size);
+ if (ret == -1) {
+ fprintf (stderr, "glusterfs_read(%s) => %s\n", filename, strerror (errno));
+ glusterfs_close (fd);
+ break;
+ }
+ glusterfs_close (fd);
+ state->io_size += ret;
+ }
+
+ return i;
+}
+
+
+int
+do_mode_libglusterfsclient_iface_fileio (struct state *state)
+{
+ if (state->need_op_write)
+ MEASURE (do_mode_libglusterfsclient_iface_fileio_write, state);
+
+ if (state->need_op_read)
+ MEASURE (do_mode_libglusterfsclient_iface_fileio_read, state);
+
+ return 0;
+}
+
+
+int
+do_mode_libglusterfsclient_iface_xattr_write (struct state *state)
+{
+ long int i;
+ int ret = -1;
+ char block[state->block_size];
+ char *dname = NULL, *dirc = NULL;
+ char *bname = NULL, *basec = NULL;
+
+ asprintf (&dirc, "/%s", state->prefix);
+ asprintf (&basec, "/%s", state->prefix);
+ dname = dirname (dirc);
+ bname = basename (basec);
+
+ for (i=0; i<state->count; i++) {
+ char key[512];
+
+ sprintf (key, "glusterfs.file.%s.%06ld", bname, i);
+
+ ret = glusterfs_setxattr (state->libglusterfsclient_context,
+ dname, key, block, state->block_size, 0);
+
+ if (ret < 0) {
+ fprintf (stderr, "glusterfs_setxattr (%s, %s, %p) => %s\n",
+ dname, key, block, strerror (errno));
+ break;
+ }
+ state->io_size += state->block_size;
+ }
+
+ return i;
+
+}
+
+
+int
+do_mode_libglusterfsclient_iface_xattr_read (struct state *state)
+{
+ long int i;
+ int ret = -1;
+ char block[state->block_size];
+ char *dname = NULL, *dirc = NULL;
+ char *bname = NULL, *basec = NULL;
+
+ dirc = strdup (state->prefix);
+ basec = strdup (state->prefix);
+ dname = dirname (dirc);
+ bname = basename (basec);
+
+ for (i=0; i<state->count; i++) {
+ char key[512];
+
+ sprintf (key, "glusterfs.file.%s.%06ld", bname, i);
+
+ ret = glusterfs_getxattr (state->libglusterfsclient_context,
+ dname, key, block, state->block_size);
+
+ if (ret < 0) {
+ fprintf (stderr, "glusterfs_getxattr (%s, %s, %p) => %s\n",
+ dname, key, block, strerror (errno));
+ break;
+ }
+ state->io_size += ret;
+ }
+
+ return i;
+}
+
+
+int
+do_mode_libglusterfsclient_iface_xattr (struct state *state)
+{
+ if (state->need_op_write)
+ MEASURE (do_mode_libglusterfsclient_iface_xattr_write, state);
+
+ if (state->need_op_read)
+ MEASURE (do_mode_libglusterfsclient_iface_xattr_read, state);
+
+ return 0;
+}
+
+
+int
+do_mode_posix (struct state *state)
+{
+ if (state->need_iface_fileio)
+ do_mode_posix_iface_fileio (state);
+
+ if (state->need_iface_xattr)
+ do_mode_posix_iface_xattr (state);
+
+ return 0;
+}
+
+
+int
+do_mode_libglusterfsclient (struct state *state)
+{
+ glusterfs_init_ctx_t ctx = {
+ .logfile = "/dev/stderr",
+ .loglevel = "error",
+ .lookup_timeout = 60,
+ .stat_timeout = 60,
+ };
+
+ ctx.specfile = state->specfile;
+ if (state->specfile) {
+ state->libglusterfsclient_context = glusterfs_init (&ctx);
+
+ if (!state->libglusterfsclient_context) {
+ fprintf (stdout, "Unable to initialize glusterfs context, skipping libglusterfsclient mode\n");
+ return -1;
+ }
+ } else {
+ fprintf (stdout, "glusterfs volume specification file not provided, skipping libglusterfsclient mode\n");
+ return -1;
+ }
+
+ if (state->need_iface_fileio)
+ do_mode_libglusterfsclient_iface_fileio (state);
+
+ if (state->need_iface_xattr)
+ do_mode_libglusterfsclient_iface_xattr (state);
+
+ return 0;
+}
+
+
+int
+do_actions (struct state *state)
+{
+ if (state->need_mode_libglusterfsclient)
+ do_mode_libglusterfsclient (state);
+
+ if (state->need_mode_posix)
+ do_mode_posix (state);
+
+ return 0;
+}
+
+static struct argp_option options[] = {
+ {"op", 'o', "OPERATIONS", 0,
+ "WRITE|READ|BOTH - defaults to BOTH"},
+ {"iface", 'i', "INTERFACE", 0,
+ "FILEIO|XATTR|BOTH - defaults to FILEIO"},
+ {"mode", 'm', "MODE", 0,
+ "POSIX|LIBGLUSTERFSCLIENT|BOTH - defaults to POSIX"},
+ {"block", 'b', "BLOCKSIZE", 0,
+ "<NUM> - defaults to 4096"},
+ {"specfile", 's', "SPECFILE", 0,
+ "absolute path to specfile"},
+ {"prefix", 'p', "PREFIX", 0,
+ "filename prefix"},
+ {"count", 'c', "COUNT", 0,
+ "number of files"},
+ {0, 0, 0, 0, 0}
+};
+
+static struct argp argp = {
+ options,
+ parse_opts,
+ "tool",
+ "tool to benchmark small file performance"
+};
+
+int
+main (int argc, char *argv[])
+{
+ struct state state = {0, };
+
+ state.need_op_write = 1;
+ state.need_op_read = 1;
+
+ state.need_iface_fileio = 1;
+ state.need_iface_xattr = 0;
+
+ state.need_mode_posix = 1;
+ state.need_mode_libglusterfsclient = 0;
+
+ state.block_size = 4096;
+
+ strcpy (state.prefix, "tmpfile");
+ state.count = 1048576;
+
+ if (argp_parse (&argp, argc, argv, 0, 0, &state) != 0) {
+ fprintf (stderr, "argp_parse() failed\n");
+ return 1;
+ }
+
+ do_actions (&state);
+
+ return 0;
+}