GNUnet  0.19.4
benchmark.c File Reference

benchmarking for various operations More...

#include "platform.h"
#include "gnunet_util_lib.h"
#include "benchmark.h"
#include <pthread.h>
#include <sys/syscall.h>
Include dependency graph for benchmark.c:

Go to the source code of this file.

Macros

#define WRITE_BENCHMARK_OP(opname)
 

Functions

static void write_benchmark_data (struct BenchmarkData *bd)
 Write benchmark data to a file. More...
 
static void main_thread_destructor ()
 Called when the main thread exits and benchmark data for it was created. More...
 
static void thread_destructor (void *cls)
 Called when a thread exits and benchmark data for it was created. More...
 
static void make_key ()
 Initialize the thread-local variable key for benchmark data. More...
 
struct BenchmarkDataget_benchmark_data (void)
 Acquire the benchmark data for the current thread, allocate if necessary. More...
 
struct UrlRequestDataget_url_benchmark_data (char *url, unsigned int status)
 Get benchmark data for a URL. More...
 

Variables

static pthread_key_t key
 Thread-local storage key for the benchmark data. More...
 
static pthread_once_t key_once = PTHREAD_ONCE_INIT
 One-time initialization marker for key. More...
 

Detailed Description

benchmarking for various operations

Author
Florian Dold flo@d.nosp@m.old..nosp@m.me

Definition in file benchmark.c.

Macro Definition Documentation

◆ WRITE_BENCHMARK_OP

#define WRITE_BENCHMARK_OP (   opname)
Value:
do { \
GNUNET_asprintf (&s, "op " #opname " count %llu time_us %llu\n", \
(unsigned long long) bd->opname ## _count, \
(unsigned long long) bd->opname ## _time.rel_value_us); \
strlen ( \
s))); \
GNUNET_free (s); \
} while (0)
static struct GNUNET_DISK_FileHandle * fh
File handle to STDIN, for reading restart/quit commands.
ssize_t GNUNET_DISK_file_write_blocking(const struct GNUNET_DISK_FileHandle *h, const void *buffer, size_t n)
Write a buffer to a file, blocking, if necessary.
Definition: disk.c:701
@ GNUNET_SYSERR

Function Documentation

◆ write_benchmark_data()

static void write_benchmark_data ( struct BenchmarkData bd)
static

Write benchmark data to a file.

Parameters
bdthe benchmark data

Definition at line 51 of file benchmark.c.

52 {
53  struct GNUNET_DISK_FileHandle *fh;
54  pid_t pid = getpid ();
55  pid_t tid = syscall (SYS_gettid);
56  char *benchmark_dir;
57  char *s;
58 
59  benchmark_dir = getenv ("GNUNET_BENCHMARK_DIR");
60 
61  if (NULL == benchmark_dir)
62  return;
63 
64  if (GNUNET_OK != GNUNET_DISK_directory_create (benchmark_dir))
65  {
66  GNUNET_break (0);
67  return;
68  }
69 
70  GNUNET_asprintf (&s, "%s/gnunet-benchmark-ops-%s-%llu-%llu.txt",
71  benchmark_dir,
72  (pid == tid) ? "main" : "thread",
73  (unsigned long long) pid,
74  (unsigned long long) tid);
75 
82  GNUNET_assert (NULL != fh);
83  GNUNET_free (s);
84 
85 #define WRITE_BENCHMARK_OP(opname) do { \
86  GNUNET_asprintf (&s, "op " #opname " count %llu time_us %llu\n", \
87  (unsigned long long) bd->opname ## _count, \
88  (unsigned long long) bd->opname ## _time.rel_value_us); \
89  GNUNET_assert (GNUNET_SYSERR != GNUNET_DISK_file_write_blocking (fh, s, \
90  strlen ( \
91  s))); \
92  GNUNET_free (s); \
93 } while (0)
94 
95  WRITE_BENCHMARK_OP (ecc_ecdh);
96  WRITE_BENCHMARK_OP (ecdh_eddsa);
97  WRITE_BENCHMARK_OP (ecdhe_key_create);
98  WRITE_BENCHMARK_OP (ecdhe_key_get_public);
99  WRITE_BENCHMARK_OP (ecdsa_ecdh);
100  WRITE_BENCHMARK_OP (ecdsa_key_create);
101  WRITE_BENCHMARK_OP (ecdsa_key_get_public);
102  WRITE_BENCHMARK_OP (ecdsa_sign);
103  WRITE_BENCHMARK_OP (ecdsa_verify);
104  WRITE_BENCHMARK_OP (eddsa_ecdh);
105  WRITE_BENCHMARK_OP (eddsa_key_create);
106  WRITE_BENCHMARK_OP (eddsa_key_get_public);
107  WRITE_BENCHMARK_OP (eddsa_sign);
108  WRITE_BENCHMARK_OP (eddsa_verify);
109  WRITE_BENCHMARK_OP (hash);
110  WRITE_BENCHMARK_OP (hash_context_finish);
111  WRITE_BENCHMARK_OP (hash_context_read);
112  WRITE_BENCHMARK_OP (hash_context_start);
113  WRITE_BENCHMARK_OP (hkdf);
114  WRITE_BENCHMARK_OP (rsa_blind);
115  WRITE_BENCHMARK_OP (rsa_private_key_create);
116  WRITE_BENCHMARK_OP (rsa_private_key_get_public);
117  WRITE_BENCHMARK_OP (rsa_sign_blinded);
118  WRITE_BENCHMARK_OP (rsa_unblind);
119  WRITE_BENCHMARK_OP (rsa_verify);
120 
121 #undef WRITE_BENCHMARK_OP
122 
124 
125  GNUNET_asprintf (&s, "%s/gnunet-benchmark-urls-%s-%llu-%llu.txt",
126  benchmark_dir,
127  (pid == tid) ? "main" : "thread",
128  (unsigned long long) pid,
129  (unsigned long long) tid);
130 
137  GNUNET_assert (NULL != fh);
138  GNUNET_free (s);
139 
140  for (unsigned int i = 0; i < bd->urd_len; i++)
141  {
142  struct UrlRequestData *urd = &bd->urd[i];
143  GNUNET_asprintf (&s,
144  "url %s status %u count %llu time_us %llu time_us_max %llu bytes_sent %llu bytes_received %llu\n",
145  urd->request_url,
146  urd->status,
147  (unsigned long long) urd->count,
148  (unsigned long long) urd->time.rel_value_us,
149  (unsigned long long) urd->time_max.rel_value_us,
150  (unsigned long long) urd->bytes_sent,
151  (unsigned long long) urd->bytes_received);
153  strlen (
154  s)));
155  GNUNET_free (s);
156  }
157 
159 }
#define WRITE_BENCHMARK_OP(opname)
char * getenv()
static struct GNUNET_SCHEDULER_Task * tid
Task identifier of the task that waits for stdin.
static struct GNUNET_PeerIdentity pid
Identity of the peer we transmit to / connect to.
struct GNUNET_DISK_FileHandle * GNUNET_DISK_file_open(const char *fn, enum GNUNET_DISK_OpenFlags flags, enum GNUNET_DISK_AccessPermissions perm)
Open a file.
Definition: disk.c:1237
enum GNUNET_GenericReturnValue GNUNET_DISK_file_close(struct GNUNET_DISK_FileHandle *h)
Close an open file.
Definition: disk.c:1308
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_create(const char *dir)
Implementation of "mkdir -p".
Definition: disk.c:496
@ GNUNET_DISK_OPEN_WRITE
Open the file for writing.
@ GNUNET_DISK_OPEN_TRUNCATE
Truncate file if it exists.
@ GNUNET_DISK_OPEN_CREATE
Create file if it doesn't exist.
@ GNUNET_DISK_PERM_USER_READ
Owner can read.
@ GNUNET_DISK_PERM_USER_WRITE
Owner can write.
@ GNUNET_OK
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_free(ptr)
Wrapper around free.
struct UrlRequestData * urd
Definition: benchmark.h:143
unsigned int urd_len
Definition: benchmark.h:145
Handle used to access files (and pipes).
uint64_t rel_value_us
The actual value.
Struct for benchmark data for one URL.
Definition: benchmark.h:66
struct GNUNET_TIME_Relative time
Total time spent requesting this URL.
Definition: benchmark.h:95
char request_url[128]
Request URL, truncated (but 0-terminated).
Definition: benchmark.h:70
unsigned int status
HTTP status code.
Definition: benchmark.h:75
uint64_t bytes_received
How many bytes were received in total as response to requesting this URL.
Definition: benchmark.h:90
struct GNUNET_TIME_Relative time_max
Slowest time to response.
Definition: benchmark.h:100
uint64_t bytes_sent
How many bytes were sent in total to request the URL.
Definition: benchmark.h:85
uint64_t count
How often was the URL requested?
Definition: benchmark.h:80

References UrlRequestData::bytes_received, UrlRequestData::bytes_sent, UrlRequestData::count, fh, getenv(), GNUNET_asprintf(), GNUNET_assert, GNUNET_break, GNUNET_DISK_directory_create(), GNUNET_DISK_file_close(), GNUNET_DISK_file_open(), GNUNET_DISK_file_write_blocking(), GNUNET_DISK_OPEN_CREATE, GNUNET_DISK_OPEN_TRUNCATE, GNUNET_DISK_OPEN_WRITE, GNUNET_DISK_PERM_USER_READ, GNUNET_DISK_PERM_USER_WRITE, GNUNET_free, GNUNET_OK, GNUNET_SYSERR, pid, GNUNET_TIME_Relative::rel_value_us, UrlRequestData::request_url, UrlRequestData::status, tid, UrlRequestData::time, UrlRequestData::time_max, BenchmarkData::urd, BenchmarkData::urd_len, and WRITE_BENCHMARK_OP.

Referenced by main_thread_destructor(), and thread_destructor().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ main_thread_destructor()

static void main_thread_destructor ( )
static

Called when the main thread exits and benchmark data for it was created.

Definition at line 166 of file benchmark.c.

167 {
168  struct BenchmarkData *bd;
169 
170  bd = pthread_getspecific (key);
171  if (NULL != bd)
173 }
static pthread_key_t key
Thread-local storage key for the benchmark data.
Definition: benchmark.c:37
static void write_benchmark_data(struct BenchmarkData *bd)
Write benchmark data to a file.
Definition: benchmark.c:51
Thread-local struct for benchmarking data.
Definition: benchmark.h:116

References key, and write_benchmark_data().

Referenced by get_benchmark_data().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ thread_destructor()

static void thread_destructor ( void *  cls)
static

Called when a thread exits and benchmark data for it was created.

Parameters
clsclosure

Definition at line 182 of file benchmark.c.

183 {
184  struct BenchmarkData *bd = cls;
185 
186  // main thread will be handled by atexit
187  if (getpid () == (pid_t) syscall (SYS_gettid))
188  return;
189 
190  GNUNET_assert (NULL != bd);
192 }

References GNUNET_assert, and write_benchmark_data().

Referenced by make_key().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ make_key()

static void make_key ( )
static

Initialize the thread-local variable key for benchmark data.

Definition at line 199 of file benchmark.c.

200 {
201  (void) pthread_key_create (&key, &thread_destructor);
202 }
static void thread_destructor(void *cls)
Called when a thread exits and benchmark data for it was created.
Definition: benchmark.c:182

References key, and thread_destructor().

Referenced by get_benchmark_data().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_benchmark_data()

struct BenchmarkData* get_benchmark_data ( void  )

Acquire the benchmark data for the current thread, allocate if necessary.

Installs handler to collect the benchmark data on thread termination.

Returns
benchmark data for the current thread

Definition at line 212 of file benchmark.c.

213 {
214  struct BenchmarkData *bd;
215 
216  (void) pthread_once (&key_once, &make_key);
217 
218  if (NULL == (bd = pthread_getspecific (key)))
219  {
220  bd = GNUNET_new (struct BenchmarkData);
221  (void) pthread_setspecific (key, bd);
222  if (getpid () == (pid_t) syscall (SYS_gettid))
223  {
224  // We're the main thread!
225  atexit (main_thread_destructor);
226  }
227  }
228  return bd;
229 }
static void make_key()
Initialize the thread-local variable key for benchmark data.
Definition: benchmark.c:199
static pthread_once_t key_once
One-time initialization marker for key.
Definition: benchmark.c:42
static void main_thread_destructor()
Called when the main thread exits and benchmark data for it was created.
Definition: benchmark.c:166
#define GNUNET_new(type)
Allocate a struct or union of the given type.

References GNUNET_new, key, key_once, main_thread_destructor(), and make_key().

Referenced by get_url_benchmark_data().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_url_benchmark_data()

struct UrlRequestData* get_url_benchmark_data ( char *  url,
unsigned int  status 
)

Get benchmark data for a URL.

If the URL is too long, it's truncated before looking up the corresponding benchmark data.

Statistics are bucketed by URL and status code.

Parameters
urlurl to get request data for
statushttp status code

Definition at line 242 of file benchmark.c.

243 {
244  char trunc[MAX_BENCHMARK_URL_LEN];
245  struct BenchmarkData *bd;
246 
247  if (NULL == url)
248  {
249  /* Should not happen unless curl barfs */
250  GNUNET_break (0);
251  url = "<empty>";
252  }
253 
254  memcpy (trunc, url, MAX_BENCHMARK_URL_LEN);
255  trunc[MAX_BENCHMARK_URL_LEN - 1] = 0;
256 
257  /* We're not interested in what's after the query string */
258  for (size_t i = 0; i < strlen (trunc); i++)
259  {
260  if (trunc[i] == '?')
261  {
262  trunc[i] = 0;
263  break;
264  }
265  }
266 
267  bd = get_benchmark_data ();
268 
269  GNUNET_assert (bd->urd_len <= bd->urd_capacity);
270 
271  for (unsigned int i = 0; i < bd->urd_len; i++)
272  {
273  if ((0 == strcmp (trunc, bd->urd[i].request_url)) &&
274  (bd->urd[i].status == status))
275  return &bd->urd[i];
276  }
277 
278  {
279  struct UrlRequestData urd = { 0 };
280 
281  memcpy (&urd.request_url, trunc, MAX_BENCHMARK_URL_LEN);
282  urd.status = status;
283 
284  if (bd->urd_len == bd->urd_capacity)
285  {
286  bd->urd_capacity = 2 * (bd->urd_capacity + 1);
287  bd->urd = GNUNET_realloc (bd->urd, bd->urd_capacity * sizeof(struct
288  UrlRequestData));
289  }
290 
291  bd->urd[bd->urd_len++] = urd;
292  return &bd->urd[bd->urd_len - 1];
293  }
294 }
struct BenchmarkData * get_benchmark_data(void)
Acquire the benchmark data for the current thread, allocate if necessary.
Definition: benchmark.c:212
#define MAX_BENCHMARK_URL_LEN
Maximum length of URLs considered for benchmarking.
Definition: benchmark.h:36
uint16_t status
See PRISM_STATUS_*-constants.
#define GNUNET_realloc(ptr, size)
Wrapper around realloc.
unsigned int urd_capacity
Definition: benchmark.h:147

References get_benchmark_data(), GNUNET_assert, GNUNET_break, GNUNET_realloc, MAX_BENCHMARK_URL_LEN, UrlRequestData::request_url, status, UrlRequestData::status, BenchmarkData::urd, BenchmarkData::urd_capacity, and BenchmarkData::urd_len.

Here is the call graph for this function:

Variable Documentation

◆ key

pthread_key_t key
static

Thread-local storage key for the benchmark data.

Definition at line 37 of file benchmark.c.

Referenced by get_benchmark_data(), main_thread_destructor(), and make_key().

◆ key_once

pthread_once_t key_once = PTHREAD_ONCE_INIT
static

One-time initialization marker for key.

Definition at line 42 of file benchmark.c.

Referenced by get_benchmark_data().