GNUnet 0.21.0
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{
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
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
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
static int status
The program status; 0 for success.
Definition: gnunet-nse.c:38
#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().