Add a microbench mark which test the performance of taking and releasing a read lease in a tight loop. Based on posix01. Signed-off-by: Daniel Wagner <daniel.wagner@xxxxxxxxxxxx> --- Makefile.am | 2 +- lease01.c | 177 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 178 insertions(+), 1 deletion(-) create mode 100644 lease01.c diff --git a/Makefile.am b/Makefile.am index 2ece31b..b0a2851 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 +bin_PROGRAMS = flock01 flock02 posix01 posix02 posix03 lease01 SUBDIRS = lib/ diff --git a/lease01.c b/lease01.c new file mode 100644 index 0000000..f3a2ae9 --- /dev/null +++ b/lease01.c @@ -0,0 +1,177 @@ +/* + * LEASE performance test 1 + * + * Fork off a given number of children who attempt to repeatedly + * acquire a read lock over the whole file and then release it for a + * given number of times. Time this to get a rough indication of lease + * locking performance for a single, contended whole-file lock. + */ + +#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 <stdbool.h> +#include <sched.h> + +#include "timespec.h" + +#define NRPROC (128) +#define NRLOCK (10240) + +static struct timespec *diff; + +static int +leaseunlease(const char *name, int nrlock, struct timespec *slot, + bool verbose, bool yield) +{ + int fd, i, ret = 0; + struct timespec start, end; + pid_t pid = getpid(); + + 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"); + return ret; + } + + if (verbose) + printf("pid:%u\n", pid); + + ret = fcntl(fd, F_SETLEASE, F_UNLCK); + ret = clock_gettime(CLOCK_MONOTONIC_RAW, &end); + if (ret) { + perror("clock_gettime"); + return ret; + } + + /* yield CPU to give another worker a chance */ + if (yield) + sched_yield(); + } + + clock_gettime(CLOCK_MONOTONIC_RAW, &end); + if (ret) { + perror("clock_gettime"); + return ret; + } + + close(fd); + *slot = timespec_sub(end, start); + + return 0; +} + +void +usage(char *prog) +{ + printf("usage: %s [-n nr_procs] [-l nr_locks] [-v] [-y] filename\n", prog); +} + +int +main(int argc, char **argv) +{ + bool verbose = false, yield = false; + int i, opt, valid = 0; + int nproc = NRPROC; + int nlock = NRLOCK; + pid_t *pids; + struct timespec total = { .tv_sec = 0, + .tv_nsec = 0 }; + + + while ((opt = getopt(argc, argv, "l:n:vy")) != -1) { + switch (opt) { + case 'l': + nlock = atoi(optarg); + break; + case 'n': + nproc = atoi(optarg); + break; + case 'v': + verbose = true; + break; + default: + usage(argv[0]); + return 1; + } + } + + if (!argv[optind]) { + usage(argv[0]); + 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(argv[optind], nlock, + &diff[i], verbose, yield); + } + + 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