File: connect-benchmark.c

package info (click to toggle)
libnbd 1.24.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 10,956 kB
  • sloc: ansic: 55,158; ml: 12,325; sh: 8,811; python: 4,757; makefile: 3,038; perl: 165; cpp: 24
file content (118 lines) | stat: -rw-r--r-- 2,634 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/* 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).  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>

#ifdef HAVE_STDATOMIC_H
#include <stdatomic.h>
#else
/* Rely on ints being atomic enough on the platform. */
#define _Atomic /**/
#endif

#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);
}