GNUnet  0.10.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); \
GNUNET_assert (GNUNET_SYSERR != GNUNET_DISK_file_write_blocking (fh, s, 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:1139
#define GNUNET_SYSERR
Definition: gnunet_common.h:79

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, strlen (s))); \
89  GNUNET_free (s); \
90 } while (0)
91 
92  WRITE_BENCHMARK_OP (ecc_ecdh);
93  WRITE_BENCHMARK_OP (ecdh_eddsa);
94  WRITE_BENCHMARK_OP (ecdhe_key_create);
95  WRITE_BENCHMARK_OP (ecdhe_key_get_public);
96  WRITE_BENCHMARK_OP (ecdsa_ecdh);
97  WRITE_BENCHMARK_OP (ecdsa_key_create);
98  WRITE_BENCHMARK_OP (ecdsa_key_get_public);
99  WRITE_BENCHMARK_OP (ecdsa_sign);
100  WRITE_BENCHMARK_OP (ecdsa_verify);
101  WRITE_BENCHMARK_OP (eddsa_ecdh);
102  WRITE_BENCHMARK_OP (eddsa_key_create);
103  WRITE_BENCHMARK_OP (eddsa_key_get_public);
104  WRITE_BENCHMARK_OP (eddsa_sign);
105  WRITE_BENCHMARK_OP (eddsa_verify);
106  WRITE_BENCHMARK_OP (hash);
107  WRITE_BENCHMARK_OP (hash_context_finish);
108  WRITE_BENCHMARK_OP (hash_context_read);
109  WRITE_BENCHMARK_OP (hash_context_start);
110  WRITE_BENCHMARK_OP (hkdf);
111  WRITE_BENCHMARK_OP (rsa_blind);
112  WRITE_BENCHMARK_OP (rsa_private_key_create);
113  WRITE_BENCHMARK_OP (rsa_private_key_get_public);
114  WRITE_BENCHMARK_OP (rsa_sign_blinded);
115  WRITE_BENCHMARK_OP (rsa_unblind);
116  WRITE_BENCHMARK_OP (rsa_verify);
117 
118 #undef WRITE_BENCHMARK_OP
119 
121 
122  GNUNET_asprintf (&s, "%s/gnunet-benchmark-urls-%s-%llu-%llu.txt",
123  benchmark_dir,
124  (pid == tid) ? "main" : "thread",
125  (unsigned long long) pid,
126  (unsigned long long) tid);
127 
128  fh = GNUNET_DISK_file_open (s,
134  GNUNET_assert (NULL != fh);
135  GNUNET_free (s);
136 
137  for (unsigned int i = 0; i < bd->urd_len; i++)
138  {
139  struct UrlRequestData *urd = &bd->urd[i];
140  GNUNET_asprintf (&s, "url %s status %u count %llu time_us %llu time_us_max %llu bytes_sent %llu bytes_received %llu\n",
141  urd->request_url,
142  urd->status,
143  (unsigned long long) urd->count,
144  (unsigned long long) urd->time.rel_value_us,
145  (unsigned long long) urd->time_max.rel_value_us,
146  (unsigned long long) urd->bytes_sent,
147  (unsigned long long) urd->bytes_received);
149  GNUNET_free (s);
150  }
151 
153 }
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:1817
uint64_t rel_value_us
The actual value.
int GNUNET_DISK_directory_create(const char *dir)
Implementation of "mkdir -p".
Definition: disk.c:714
#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:78
Struct for benchmark data for one URL.
Definition: benchmark.h:61
struct GNUNET_TIME_Relative time_max
Slowest time to response.
Definition: benchmark.h:96
#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:76
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
struct UrlRequestData * urd
Definition: benchmark.h:139
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:81
struct GNUNET_TIME_Relative time
Total time spent requesting this URL.
Definition: benchmark.h:91
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:1139
unsigned int urd_len
Definition: benchmark.h:141
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
uint64_t bytes_received
How many bytes were received in total as response to requesting this URL.
Definition: benchmark.h:86
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:71
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:1673
#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:66
#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 160 of file benchmark.c.

References key, and write_benchmark_data().

Referenced by get_benchmark_data().

161 {
162  struct BenchmarkData *bd;
163 
164  bd = pthread_getspecific (key);
165  if (NULL != bd)
167 }
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:111
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 176 of file benchmark.c.

References GNUNET_assert, and write_benchmark_data().

Referenced by make_key().

177 {
178  struct BenchmarkData *bd = cls;
179 
180  // main thread will be handled by atexit
181  if (getpid () == (pid_t) syscall (SYS_gettid))
182  return;
183 
184  GNUNET_assert (NULL != bd);
186 }
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:111
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 193 of file benchmark.c.

References key, and thread_destructor().

Referenced by get_benchmark_data().

194 {
195  (void) pthread_key_create (&key, &thread_destructor);
196 }
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:176
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 206 of file benchmark.c.

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

Referenced by get_url_benchmark_data().

207 {
208  struct BenchmarkData *bd;
209 
210  (void) pthread_once (&key_once, &make_key);
211 
212  if (NULL == (bd = pthread_getspecific (key)))
213  {
214  bd = GNUNET_new (struct BenchmarkData);
215  (void) pthread_setspecific (key, bd);
216  if (getpid () == (pid_t) syscall (SYS_gettid))
217  {
218  // We're the main thread!
219  atexit (main_thread_destructor);
220  }
221  }
222  return bd;
223 }
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:111
static void main_thread_destructor()
Called when the main thread exits and benchmark data for it was created.
Definition: benchmark.c:160
static void make_key()
Initialize the thread-local variable key for benchmark data.
Definition: benchmark.c:193
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 236 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().

237 {
238  char trunc[MAX_BENCHMARK_URL_LEN];
239  struct BenchmarkData *bd;
240 
241  if (NULL == url)
242  {
243  /* Should not happen unless curl barfs */
244  GNUNET_break (0);
245  url = "<empty>";
246  }
247 
248  memcpy (trunc, url, MAX_BENCHMARK_URL_LEN);
249  trunc[MAX_BENCHMARK_URL_LEN - 1] = 0;
250 
251  /* We're not interested in what's after the query string */
252  for (size_t i = 0; i < strlen (trunc); i++)
253  {
254  if (trunc[i] == '?')
255  {
256  trunc[i] = 0;
257  break;
258  }
259  }
260 
261  bd = get_benchmark_data ();
262 
263  GNUNET_assert (bd->urd_len <= bd->urd_capacity);
264 
265  for (unsigned int i = 0; i < bd->urd_len; i++)
266  {
267  if ( (0 == strcmp (trunc, bd->urd[i].request_url)) &&
268  (bd->urd[i].status == status) )
269  return &bd->urd[i];
270  }
271 
272  {
273  struct UrlRequestData urd = { 0 };
274 
275  memcpy (&urd.request_url, trunc, MAX_BENCHMARK_URL_LEN);
276  urd.status = status;
277 
278  if (bd->urd_len == bd->urd_capacity)
279  {
280  bd->urd_capacity = 2 * (bd->urd_capacity + 1);
281  bd->urd = GNUNET_realloc (bd->urd, bd->urd_capacity * sizeof (struct UrlRequestData));
282  }
283 
284  bd->urd[bd->urd_len++] = urd;
285  return &bd->urd[bd->urd_len - 1];
286  }
287 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
Struct for benchmark data for one URL.
Definition: benchmark.h:61
#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:139
#define GNUNET_realloc(ptr, size)
Wrapper around realloc.
uint16_t status
See PRISM_STATUS_*-constants.
Thread-local struct for benchmarking data.
Definition: benchmark.h:111
unsigned int urd_len
Definition: benchmark.h:141
#define MAX_BENCHMARK_URL_LEN
Maximum length of URLs considered for benchmarking.
Definition: benchmark.h:36
unsigned int urd_capacity
Definition: benchmark.h:143
unsigned int status
HTTP status code.
Definition: benchmark.h:71
struct BenchmarkData * get_benchmark_data(void)
Acquire the benchmark data for the current thread, allocate if necessary.
Definition: benchmark.c:206
char request_url[128]
Request URL, truncated (but 0-terminated).
Definition: benchmark.h:66
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().