Add a microbench mark which test the performance of taking and releasing a read lease with many processes in a tight loop. Based on posix02. Signed-off-by: Daniel Wagner <daniel.wagner@xxxxxxxxxxxx> --- Makefile.am | 2 +- lease02.c | 178 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 179 insertions(+), 1 deletion(-) create mode 100644 lease02.c diff --git a/Makefile.am b/Makefile.am index b0a2851..4a2ae98 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4,6 +4,6 @@ ACLOCAL_AMFLAGS = -I m4 EXTRA_DIST = m4/gnulib-cache.m4 LDADD = lib/libgnu.a -lrt -bin_PROGRAMS = flock01 flock02 posix01 posix02 posix03 lease01 +bin_PROGRAMS = flock01 flock02 posix01 posix02 posix03 lease01 lease02 SUBDIRS = lib/ diff --git a/lease02.c b/lease02.c new file mode 100644 index 0000000..0fa33e4 --- /dev/null +++ b/lease02.c @@ -0,0 +1,178 @@ +/* + * Lease performance test 2 + * + * Fork off a given number of children who each open their own + * file. Then have each child take a read lease and release the lease + * for the given number of times. + * + * Time this to measure lease performance for lease heavy workloads where the + * locks are generally uncontended. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <stdlib.h> +#include <time.h> +#include <sys/mman.h> + +#include "timespec.h" + +#define NRPROC (128) +#define NRLOCK (20480) + +static struct timespec *diff; + +static int +leaseunlease(int nrlock, struct timespec *slot) +{ + int fd, i, ret; + pid_t pid = getpid(); + char name[10]; /* big enough for pid_t in hex + NULL */ + struct timespec start, end; + + ret = snprintf(name, sizeof(name), "%x", pid); + if (ret >= (int)sizeof(name)) { + perror("sprintf"); + return 1; + } + + fd = open(name, O_CREAT|O_RDONLY, 0644); + if (fd < 0) { + perror("open"); + return fd; + } + + ret = clock_gettime(CLOCK_MONOTONIC_RAW, &start); + if (ret) { + perror("clock_gettime"); + return ret; + } + + for (i = 0; i < nrlock; ++i) { + ret = fcntl(fd, F_SETLEASE, F_RDLCK); + if (ret < 0) { + perror("fcntl"); + break; + } + ret = fcntl(fd, F_SETLEASE, F_RDLCK); + if (ret < 0) { + perror("fcntl"); + break; + } + } + + ret = clock_gettime(CLOCK_MONOTONIC_RAW, &end); + if (ret) { + perror("clock_gettime"); + return ret; + } + + close(fd); + *slot = timespec_sub(end, start); + return ret; +} + +void +usage(char *prog) +{ + printf("usage: %s [-n nr_procs] [-l nr_locks] directory\n", prog); +} + +int +main(int argc, char **argv) +{ + int i, opt, valid = 0; + int nproc = NRPROC; + int nlock = NRLOCK; + pid_t *pids; + char *dirname; + struct timespec total = { .tv_sec = 0, + .tv_nsec = 0 }; + + while ((opt = getopt(argc, argv, "l:n:")) != -1) { + switch (opt) { + case 'l': + nlock = atoi(optarg); + break; + case 'n': + nproc = atoi(optarg); + break; + default: + usage(argv[0]); + return 1; + } + } + + dirname = argv[optind]; + if (!dirname) { + usage(argv[0]); + return 1; + } + + if (mkdir(dirname, S_IRWXU)) { + perror("mkdir"); + return 1; + } + + if (chdir(dirname)) { + perror("chdir"); + return 1; + } + + pids = calloc(nproc, sizeof(pid_t)); + if (!pids) { + fprintf(stderr, "Unable to allocate pids array!"); + return 1; + } + + diff = mmap(0, nproc * sizeof(*diff), PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_SHARED, -1, 0); + if (diff == (struct timespec *)-1) { + fprintf(stderr, "Unable to allocate timespec array!"); + return 1; + } + + for (i = 0; i < nproc; ++i) { + pids[i] = fork(); + if (!pids[i]) + return leaseunlease(nlock, &diff[i]); + } + + for (i = 0; i < nproc; ++i) { + int status; + + if (pids[i] < 0) { + fprintf(stderr, "process %d failed to fork\n", i); + continue; + } + if (waitpid(pids[i], &status, 0) < 0) { + fprintf(stderr, "unable to reap pid %d\n", pids[i]); + continue; + } + if (!WIFEXITED(status) || WEXITSTATUS(status)) { + fprintf(stderr, "pid %d exited abnormally(0x%x)\n", pids[i],status); + continue; + } + total = timespec_add(total, diff[i]); + ++valid; + } + + if (valid != nproc) { + fprintf(stderr, "Some children didn't run properly -- " + "requested %d but only got %d\n", nproc, valid); + return 1; + } + + printf("%ld.%ld\n", total.tv_sec, total.tv_nsec); + return 0; +} -- 2.1.0 -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html