--- .gitignore | 1 + examples/Makefile.am | 16 +++++ examples/connect-benchmark.c | 112 +++++++++++++++++++++++++++++++++++ 3 files changed, 129 insertions(+)
diff --git a/.gitignore b/.gitignore index 0d4bef92c..7bc0a6778 100644 --- a/.gitignore +++ b/.gitignore @@ -70,6 +70,7 @@ Makefile.in /dump/nbddump.1 /examples/aio-connect-read /examples/batched-read-write +/examples/connect-benchmark /examples/connect-command /examples/connect-uri /examples/copy-libev diff --git a/examples/Makefile.am b/examples/Makefile.am index bad22cb11..b52996a24 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -22,6 +22,7 @@ EXTRA_DIST = LICENSE-FOR-EXAMPLES noinst_PROGRAMS = \ aio-connect-read \ batched-read-write \ + connect-benchmark \ connect-command \ connect-uri \ encryption \ @@ -62,6 +63,21 @@ batched_read_write_LDADD = \ $(top_builddir)/lib/libnbd.la \ $(NULL) +connect_benchmark_SOURCES = \ + connect-benchmark.c \ + $(NULL) +connect_benchmark_CPPFLAGS = \ + -I$(top_srcdir)/include \ + $(NULL) +connect_benchmark_CFLAGS = \ + $(WARNINGS_CFLAGS) \ + $(PTHREAD_CFLAGS) \ + $(NULL) +connect_benchmark_LDADD = \ + $(top_builddir)/lib/libnbd.la \ + $(PTHREAD_LIBS) \ + $(NULL) + connect_command_SOURCES = \ connect-command.c \ $(NULL) diff --git a/examples/connect-benchmark.c b/examples/connect-benchmark.c new file mode 100644 index 000000000..1e153b915 --- /dev/null +++ b/examples/connect-benchmark.c @@ -0,0 +1,112 @@ +/* The example benchmarks multiple parallel connections to an NBD + * server. You can use it to time how long it takes to connect under + * various circumstances (eg. TLS vs no TLS, old vs newstyle, with or + * without TCP fastopen). It only does the NBD handshake and then + * immediately disconnects. + * + * Typical usage: + * ./examples/connect-benchmark nbd://localhost 16 1000 + * where the parameters are: + * URI of the server + * number of threads + * total number of connections to make (across all threads) + * + * Or: + * nbdkit null --run './examples/connect-benchmark "$uri" 16 1000' + * + * Use 'hyperfine' to time multiple runs. + */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <stdbool.h> +#include <stdint.h> +#include <inttypes.h> +#include <errno.h> + +#include <pthread.h> + +#include <libnbd.h> + +static const char *uri; +static unsigned nr_threads, nr_connections; +static _Atomic unsigned count = 0; + +static void *start_thread (void *arg); + +int +main (int argc, char *argv[]) +{ + pthread_t *threads; + unsigned i; + int err; + + if (argc != 4) { + fprintf (stderr, "%s URI threads connections\n", argv[0]); + exit (EXIT_FAILURE); + } + uri = argv[1]; + if (sscanf (argv[2], "%u", &nr_threads) != 1 || + sscanf (argv[3], "%u", &nr_connections) != 1) { + fprintf (stderr, "%s: cannot read number of threads or connections\n", + argv[0]); + exit (EXIT_FAILURE); + } + + threads = calloc (nr_threads, sizeof threads[0]); + if (threads == NULL) { + perror ("calloc"); + exit (EXIT_FAILURE); + } + + /* Start the worker threads, one per connection. */ + for (i = 0; i < nr_threads; ++i) { + err = pthread_create (&threads[i], NULL, start_thread, NULL); + if (err != 0) { + errno = err; + perror ("pthread_create"); + exit (EXIT_FAILURE); + } + } + + /* Wait for the threads to exit. */ + for (i = 0; i < nr_threads; ++i) { + err = pthread_join (threads[i], NULL); + if (err != 0) { + errno = err; + perror ("pthread_join"); + exit (EXIT_FAILURE); + } + } + + exit (EXIT_SUCCESS); +} + +static void * +start_thread (void *arg) +{ + struct nbd_handle *nbd; + unsigned i; + + for (;;) { + i = count++; + if (i >= nr_connections) break; + + nbd = nbd_create (); + if (nbd == NULL) { + fprintf (stderr, "%s\n", nbd_get_error ()); + exit (EXIT_FAILURE); + } + + if (nbd_connect_uri (nbd, uri) == -1) { + fprintf (stderr, "%s\n", nbd_get_error ()); + exit (EXIT_FAILURE); + } + + nbd_close (nbd); + } + + pthread_exit (NULL); +} -- 2.46.0 _______________________________________________ Libguestfs mailing list -- guestfs@lists.libguestfs.org To unsubscribe send an email to guestfs-le...@lists.libguestfs.org