GNUnet  0.11.x
Macros | Functions | Variables
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 int fh
Handle to the unique file.
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:844
#define GNUNET_SYSERR
Definition: gnunet_common.h:76

Referenced by write_benchmark_data().

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 50 of file benchmark.c.

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().

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

References key, and write_benchmark_data().

Referenced by get_benchmark_data().

166 {
167  struct BenchmarkData *bd;
168 
169  bd = pthread_getspecific (key);
170  if (NULL != bd)
172 }
static pthread_key_t key
Thread-local storage key for the benchmark data.
Definition: benchmark.c:36
static void write_benchmark_data(struct BenchmarkData *bd)
Write benchmark data to a file.
Definition: benchmark.c:50
Thread-local struct for benchmarking data.
Definition: benchmark.h:115
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 181 of file benchmark.c.

References GNUNET_assert, and write_benchmark_data().

Referenced by make_key().

182 {
183  struct BenchmarkData *bd = cls;
184 
185  // main thread will be handled by atexit
186  if (getpid () == (pid_t) syscall (SYS_gettid))
187  return;
188 
189  GNUNET_assert (NULL != bd);
191 }
static void write_benchmark_data(struct BenchmarkData *bd)
Write benchmark data to a file.
Definition: benchmark.c:50
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
Thread-local struct for benchmarking data.
Definition: benchmark.h:115
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 198 of file benchmark.c.

References key, and thread_destructor().

Referenced by get_benchmark_data().

199 {
200  (void) pthread_key_create (&key, &thread_destructor);
201 }
static pthread_key_t key
Thread-local storage key for the benchmark data.
Definition: benchmark.c:36
static void thread_destructor(void *cls)
Called when a thread exits and benchmark data for it was created.
Definition: benchmark.c:181
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 211 of file benchmark.c.

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

Referenced by get_url_benchmark_data().

212 {
213  struct BenchmarkData *bd;
214 
215  (void) pthread_once (&key_once, &make_key);
216 
217  if (NULL == (bd = pthread_getspecific (key)))
218  {
219  bd = GNUNET_new (struct BenchmarkData);
220  (void) pthread_setspecific (key, bd);
221  if (getpid () == (pid_t) syscall (SYS_gettid))
222  {
223  // We're the main thread!
224  atexit (main_thread_destructor);
225  }
226  }
227  return bd;
228 }
static pthread_once_t key_once
One-time initialization marker for key.
Definition: benchmark.c:41
static pthread_key_t key
Thread-local storage key for the benchmark data.
Definition: benchmark.c:36
#define GNUNET_new(type)
Allocate a struct or union of the given type.
Thread-local struct for benchmarking data.
Definition: benchmark.h:115
static void main_thread_destructor()
Called when the main thread exits and benchmark data for it was created.
Definition: benchmark.c:165
static void make_key()
Initialize the thread-local variable key for benchmark data.
Definition: benchmark.c:198
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 correspoding benchmark data.

Statistics are bucketed by URL and status code.

Parameters
urlurl to get request data for
statushttp status code

Definition at line 241 of file benchmark.c.

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

Referenced by GNUNET_CURL_perform2().

242 {
243  char trunc[MAX_BENCHMARK_URL_LEN];
244  struct BenchmarkData *bd;
245 
246  if (NULL == url)
247  {
248  /* Should not happen unless curl barfs */
249  GNUNET_break (0);
250  url = "<empty>";
251  }
252 
253  memcpy (trunc, url, MAX_BENCHMARK_URL_LEN);
254  trunc[MAX_BENCHMARK_URL_LEN - 1] = 0;
255 
256  /* We're not interested in what's after the query string */
257  for (size_t i = 0; i < strlen (trunc); i++)
258  {
259  if (trunc[i] == '?')
260  {
261  trunc[i] = 0;
262  break;
263  }
264  }
265 
266  bd = get_benchmark_data ();
267 
268  GNUNET_assert (bd->urd_len <= bd->urd_capacity);
269 
270  for (unsigned int i = 0; i < bd->urd_len; i++)
271  {
272  if ((0 == strcmp (trunc, bd->urd[i].request_url)) &&
273  (bd->urd[i].status == status))
274  return &bd->urd[i];
275  }
276 
277  {
278  struct UrlRequestData urd = { 0 };
279 
280  memcpy (&urd.request_url, trunc, MAX_BENCHMARK_URL_LEN);
281  urd.status = status;
282 
283  if (bd->urd_len == bd->urd_capacity)
284  {
285  bd->urd_capacity = 2 * (bd->urd_capacity + 1);
286  bd->urd = GNUNET_realloc (bd->urd, bd->urd_capacity * sizeof(struct
287  UrlRequestData));
288  }
289 
290  bd->urd[bd->urd_len++] = urd;
291  return &bd->urd[bd->urd_len - 1];
292  }
293 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
Struct for benchmark data for one URL.
Definition: benchmark.h:65
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
struct UrlRequestData * urd
Definition: benchmark.h:143
#define GNUNET_realloc(ptr, size)
Wrapper around realloc.
uint16_t status
See PRISM_STATUS_*-constants.
Thread-local struct for benchmarking data.
Definition: benchmark.h:115
unsigned int urd_len
Definition: benchmark.h:145
#define MAX_BENCHMARK_URL_LEN
Maximum length of URLs considered for benchmarking.
Definition: benchmark.h:36
unsigned int urd_capacity
Definition: benchmark.h:147
unsigned int status
HTTP status code.
Definition: benchmark.h:75
struct BenchmarkData * get_benchmark_data(void)
Acquire the benchmark data for the current thread, allocate if necessary.
Definition: benchmark.c:211
char request_url[128]
Request URL, truncated (but 0-terminated).
Definition: benchmark.h:70
Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ key

pthread_key_t key
static

Thread-local storage key for the benchmark data.

Definition at line 36 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 41 of file benchmark.c.

Referenced by get_benchmark_data().