Rename BUFFER_SIZE to REQUEST_SIZE and get the value from an environment
variable. Change the test script to test multiple values.

An example run:

$ ./synch-parallel.sh
Request size: 4096
thread 0: finished OK in 10.000019 seconds
thread 4: finished OK in 10.000003 seconds
thread 2: finished OK in 10.000015 seconds
thread 1: finished OK in 10.000053 seconds
thread 6: finished OK in 10.000075 seconds
thread 7: finished OK in 10.000012 seconds
thread 3: finished OK in 10.000024 seconds
thread 5: finished OK in 10.000000 seconds
TLS: disabled
bytes sent: 2412867584 (230.109 MiB/s)
bytes received: 2419851264 (230.775 MiB/s)
I/O requests: 1179863 (117986 IOPS)

Request size: 262144
thread 2: finished OK in 10.000030 seconds
thread 5: finished OK in 10.000415 seconds
thread 1: finished OK in 10.000500 seconds
thread 3: finished OK in 10.000459 seconds
thread 6: finished OK in 10.000275 seconds
thread 4: finished OK in 10.000520 seconds
thread 7: finished OK in 10.000529 seconds
thread 0: finished OK in 10.000768 seconds
TLS: disabled
bytes sent: 12791840768 (1219.92 MiB/s)
bytes received: 12748324864 (1215.78 MiB/s)
I/O requests: 97428 (9742.8 IOPS)

4k is a good size to test IOPS, and 256k is a good size for getting
maximum throughput. I kept the current default 16k as is.

Signed-off-by: Nir Soffer <[email protected]>
---
 tests/synch-parallel.c  | 51 +++++++++++++++++++++++++++++++++--------
 tests/synch-parallel.sh | 12 ++++++----
 2 files changed, 49 insertions(+), 14 deletions(-)

diff --git a/tests/synch-parallel.c b/tests/synch-parallel.c
index 423e1f0..d6ab1df 100644
--- a/tests/synch-parallel.c
+++ b/tests/synch-parallel.c
@@ -36,82 +36,115 @@
 #include <sys/time.h>
 
 #include <pthread.h>
 
 #include <libnbd.h>
 
 #include "byte-swapping.h"
 
 /* We keep a shadow of the RAM disk so we can check integrity of the data. */
 static char *ramdisk;
 
 /* This is also defined in synch-parallel.sh and checked here. */
 #define EXPORTSIZE (8*1024*1024)
 
 /* How long (seconds) that the test will run for. */
 #define RUN_TIME 10
 
 /* Number of threads. */
 #define NR_THREADS 8
 
-#define MiB (1024*1024)
+#define KiB 1024
+#define MiB (1024*KiB)
 
 #define MICROSECONDS 1000000
 
 /* Unix socket. */
 static const char *unixsocket;
 
+static long request_size;
+
 struct thread_status {
   size_t i;                     /* Thread index, 0 .. NR_THREADS-1 */
   uint64_t offset, length;      /* Area assigned to this thread. */
   int status;                   /* Return status. */
   unsigned requests;            /* Total number of requests made. */
   uint64_t bytes_sent, bytes_received; /* Bytes sent and received by thread. */
 };
 
 static void *start_thread (void *arg);
 
 static inline int64_t
 microtime (void)
 {
   struct timeval tv;
 
   gettimeofday(&tv, NULL);
   return tv.tv_sec * MICROSECONDS + tv.tv_usec;
 }
 
+static long
+getenv_long(const char *name, long defval)
+{
+  const char *value;
+  char *end;
+  long res;
+
+  value = getenv (name);
+  if (value == NULL)
+    return defval;
+
+  res = strtol(value, &end, 10);
+  if (*end != '\0' || end == value) {
+    fprintf (stderr, "Invalid value for %s: '%s'\n", name, value);
+    exit (EXIT_FAILURE);
+  }
+
+  return res;
+}
+
 int
 main (int argc, char *argv[])
 {
   pthread_t threads[NR_THREADS];
   struct thread_status status[NR_THREADS];
   size_t i;
   int err;
   unsigned requests, errors;
   uint64_t bytes_sent, bytes_received;
 
   if (argc != 2) {
     fprintf (stderr, "%s socket\n", argv[0]);
     exit (EXIT_FAILURE);
   }
   unixsocket = argv[1];
 
+  request_size = getenv_long ("REQUEST_SIZE", 16*KiB);
+  if (request_size < 4*KiB ||
+      request_size > 512*KiB ||
+      (EXPORTSIZE / NR_THREADS) % request_size != 0) {
+    fprintf (stderr,
+             "Invalid REQUEST_SIZE environment variable: %ld\n",
+             request_size);
+    exit (EXIT_FAILURE);
+  }
+
   srand ((microtime () / MICROSECONDS) + getpid ());
 
   /* Initialize the RAM disk with the initial data from
    * nbdkit-pattern-filter.
    */
   ramdisk = malloc (EXPORTSIZE);
   if (ramdisk == NULL) {
     perror ("calloc");
     exit (EXIT_FAILURE);
   }
   for (i = 0; i < EXPORTSIZE; i += 8) {
     uint64_t d = htobe64 (i);
     memcpy (&ramdisk[i], &d, sizeof d);
   }
 
   /* Start the worker threads. */
   for (i = 0; i < NR_THREADS; ++i) {
     status[i].i = i;
     status[i].offset = i * EXPORTSIZE / NR_THREADS;
     status[i].length = EXPORTSIZE / NR_THREADS;
@@ -152,53 +185,51 @@ main (int argc, char *argv[])
   /* Print some stats. */
   printf ("TLS: %s\n",
 #ifdef TLS
           "enabled"
 #else
           "disabled"
 #endif
           );
 
   printf ("bytes sent: %" PRIu64 " (%g MiB/s)\n",
           bytes_sent, (double) bytes_sent / RUN_TIME / MiB);
   printf ("bytes received: %" PRIu64 " (%g MiB/s)\n",
           bytes_received, (double) bytes_received / RUN_TIME / MiB);
 
   printf ("I/O requests: %u (%g IOPS)\n",
           requests, (double) requests / RUN_TIME);
 
   exit (errors == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
 }
 
-#define BUFFER_SIZE 16384
-
 static void *
 start_thread (void *arg)
 {
   struct thread_status *status = arg;
   struct nbd_handle *nbd;
   char *buf;
   int cmd;
   uint64_t offset;
   int64_t start_usec, stop_usec, now_usec;
 
-  buf = calloc (BUFFER_SIZE, 1);
+  buf = calloc (request_size, 1);
   if (buf == NULL) {
     perror ("calloc");
     exit (EXIT_FAILURE);
   }
 
   nbd = nbd_create ();
   if (nbd == NULL) {
     fprintf (stderr, "%s\n", nbd_get_error ());
     exit (EXIT_FAILURE);
   }
 
 #ifdef TLS
   /* Require TLS on the handle and fail if not available or if the
    * handshake fails.
    */
   if (nbd_set_tls (nbd, LIBNBD_TLS_REQUIRE) == -1) {
     fprintf (stderr, "%s\n", nbd_get_error ());
     exit (EXIT_FAILURE);
   }
 
@@ -217,58 +248,58 @@ start_thread (void *arg)
   if (nbd_connect_unix (nbd, unixsocket) == -1) {
     fprintf (stderr, "%s\n", nbd_get_error ());
     exit (EXIT_FAILURE);
   }
 
   assert (nbd_get_size (nbd) == EXPORTSIZE);
   assert (nbd_can_multi_conn (nbd) > 0);
   assert (nbd_is_read_only (nbd) == 0);
 
   start_usec = microtime ();
   stop_usec = start_usec + RUN_TIME * MICROSECONDS;
 
   /* Issue commands. */
   while (1) {
     /* Run until the timer expires. */
     now_usec = microtime ();
     if (now_usec >= stop_usec)
       break;
 
     /* Issue a synchronous read or write command. */
-    offset = status->offset + (rand () % (status->length - BUFFER_SIZE));
+    offset = status->offset + (rand () % (status->length - request_size));
     cmd = rand () & 1;
     if (cmd == 0) {
       /* Write block from ramdisk to nbd server. */
-      if (nbd_pwrite (nbd, &ramdisk[offset], BUFFER_SIZE, offset, 0) == -1) {
+      if (nbd_pwrite (nbd, &ramdisk[offset], request_size, offset, 0) == -1) {
         fprintf (stderr, "%s\n", nbd_get_error ());
         goto error;
       }
-      status->bytes_sent += BUFFER_SIZE;
+      status->bytes_sent += request_size;
     }
     else {
       /* Read block from nbd server to buf. */
-      if (nbd_pread (nbd, buf, BUFFER_SIZE, offset, 0) == -1) {
+      if (nbd_pread (nbd, buf, request_size, offset, 0) == -1) {
         fprintf (stderr, "%s\n", nbd_get_error ());
         goto error;
       }
-      status->bytes_received += BUFFER_SIZE;
-      if (memcmp (&ramdisk[offset], buf, BUFFER_SIZE) != 0) {
+      status->bytes_received += request_size;
+      if (memcmp (&ramdisk[offset], buf, request_size) != 0) {
         fprintf (stderr, "thread %zu: DATA INTEGRITY ERROR!\n", status->i);
         goto error;
       }
     }
     status->requests++;
   }
 
   printf ("thread %zu: finished OK in %.6f seconds\n",
           status->i, (double) (now_usec - start_usec) / MICROSECONDS);
 
   if (nbd_shutdown (nbd, 0) == -1) {
     fprintf (stderr, "%s\n", nbd_get_error ());
     goto error;
   }
 
   nbd_close (nbd);
 
   free (buf);
 
   status->status = 0;
diff --git a/tests/synch-parallel.sh b/tests/synch-parallel.sh
index 84c00d8..0ca9060 100755
--- a/tests/synch-parallel.sh
+++ b/tests/synch-parallel.sh
@@ -1,24 +1,28 @@
 #!/usr/bin/env bash
 # nbd client library in userspace
 # Copyright (C) 2019 Red Hat Inc.
 #
 # This library is free software; you can redistribute it and/or
 # modify it under the terms of the GNU Lesser General Public
 # License as published by the Free Software Foundation; either
 # version 2 of the License, or (at your option) any later version.
 #
 # This library 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
 # Lesser General Public License for more details.
 #
 # You should have received a copy of the GNU Lesser General Public
 # License along with this library; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
 # Test synchronous parallel high level API requests.
 
-nbdkit -U - \
-       --filter=cow \
-       pattern size=8M \
-       --run '$VG ./synch-parallel $unixsocket'
+for request_size in 4096 262144; do
+    echo "Request size: $request_size"
+    REQUEST_SIZE=$request_size nbdkit -U - \
+           --filter=cow \
+           pattern size=8M \
+           --run '$VG ./synch-parallel $unixsocket'
+    echo
+done
-- 
2.31.1

_______________________________________________
Libguestfs mailing list
[email protected]
https://listman.redhat.com/mailman/listinfo/libguestfs

Reply via email to