aboutsummaryrefslogtreecommitdiff
path: root/src/util/benchmark.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/benchmark.c')
-rw-r--r--src/util/benchmark.c293
1 files changed, 0 insertions, 293 deletions
diff --git a/src/util/benchmark.c b/src/util/benchmark.c
deleted file mode 100644
index 12efde706..000000000
--- a/src/util/benchmark.c
+++ /dev/null
@@ -1,293 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2018 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file util/benchmark.c
23 * @brief benchmarking for various operations
24 * @author Florian Dold <flo@dold.me>
25 */
26
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "benchmark.h"
30#include <pthread.h>
31#include <sys/syscall.h>
32
33/**
34 * Thread-local storage key for the benchmark data.
35 */
36static pthread_key_t key;
37
38/**
39 * One-time initialization marker for key.
40 */
41static pthread_once_t key_once = PTHREAD_ONCE_INIT;
42
43
44/**
45 * Write benchmark data to a file.
46 *
47 * @param bd the benchmark data
48 */
49static void
50write_benchmark_data (struct BenchmarkData *bd)
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,
76 (GNUNET_DISK_OPEN_WRITE
77 | GNUNET_DISK_OPEN_TRUNCATE
78 | GNUNET_DISK_OPEN_CREATE),
79 (GNUNET_DISK_PERM_USER_READ
80 | GNUNET_DISK_PERM_USER_WRITE));
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
122 GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fh));
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,
131 (GNUNET_DISK_OPEN_WRITE
132 | GNUNET_DISK_OPEN_TRUNCATE
133 | GNUNET_DISK_OPEN_CREATE),
134 (GNUNET_DISK_PERM_USER_READ
135 | GNUNET_DISK_PERM_USER_WRITE));
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);
151 GNUNET_assert (GNUNET_SYSERR != GNUNET_DISK_file_write_blocking (fh, s,
152 strlen (
153 s)));
154 GNUNET_free (s);
155 }
156
157 GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fh));
158}
159
160
161/**
162 * Called when the main thread exits and benchmark data for it was created.
163 */
164static void
165main_thread_destructor ()
166{
167 struct BenchmarkData *bd;
168
169 bd = pthread_getspecific (key);
170 if (NULL != bd)
171 write_benchmark_data (bd);
172}
173
174
175/**
176 * Called when a thread exits and benchmark data for it was created.
177 *
178 * @param cls closure
179 */
180static void
181thread_destructor (void *cls)
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);
190 write_benchmark_data (bd);
191}
192
193
194/**
195 * Initialize the thread-local variable key for benchmark data.
196 */
197static void
198make_key ()
199{
200 (void) pthread_key_create (&key, &thread_destructor);
201}
202
203
204/**
205 * Acquire the benchmark data for the current thread, allocate if necessary.
206 * Installs handler to collect the benchmark data on thread termination.
207 *
208 * @return benchmark data for the current thread
209 */
210struct BenchmarkData *
211get_benchmark_data (void)
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}
229
230
231/**
232 * Get benchmark data for a URL. If the URL is too long, it's truncated
233 * before looking up the corresponding benchmark data.
234 *
235 * Statistics are bucketed by URL and status code.
236 *
237 * @param url url to get request data for
238 * @param status http status code
239 */
240struct UrlRequestData *
241get_url_benchmark_data (char *url, unsigned int status)
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}