--- /dev/null
+# This file is part of GNUnet
+# Copyright (C) 2018 GNUnet e.V.
+#
+# GNUnet is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Affero General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# GNUnet is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+
+# Aggregate benchmarking data from multiple threads/processes
+# generated by util/benchmark.c.
+#
+# Can be used as
+# awk -f collect_ops.awk gnunet-benchmark-ops-*.txt
+
+
+# records are of the following form:
+# op <op> count <count> time_us <time_us>
+{
+ op[$2]["count"] += $4;
+ op[$2]["time_us"] += $6;
+}
+
+function avg(s, c) {
+ if (c == 0) {
+ return 0;
+ } else {
+ return s / c;
+ }
+}
+
+END {
+ for (x in op) {
+ print "op", x, "count", op[x]["count"], "time_us", op[x]["time_us"], \
+ "time_avg_us", avg(op[x]["time_us"], op[x]["count"]);
+ }
+}
--- /dev/null
+# records are of the following form:
+# This file is part of GNUnet
+# Copyright (C) 2018 GNUnet e.V.
+#
+# GNUnet is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Affero General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# GNUnet is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+
+# Aggregate benchmarking data from multiple threads/processes
+# generated by util/benchmark.c.
+#
+# Can be used as
+# awk -f collect_ops.awk gnunet-benchmark-ops-*.txt
+# url <url> status <status> count <count> time_us <time_us>
+
+{
+ url[$2][$4]["count"] += $6;
+ url[$2][$4]["time_us"] += $8;
+}
+
+function avg(s, c) {
+ if (c == 0) {
+ return 0;
+ } else {
+ return s / c;
+ }
+}
+
+END {
+ for (x in url) {
+ for (y in url[x]) {
+ print "url", x, "status", y, \
+ "count", url[x][y]["count"], "time_us", url[x][y]["time_us"], \
+ "time_avg_us", avg(url[x][y]["time_us"], url[x][y]["count"]);
+ }
+ }
+}
struct GNUNET_DISK_FileHandle *fh;
pid_t pid = getpid ();
pid_t tid = syscall (SYS_gettid);
+ char *benchmark_dir;
char *s;
- GNUNET_asprintf (&s, "gnunet-benchmark-%llu-%llu.txt",
+ benchmark_dir = getenv ("GNUNET_BENCHMARK_DIR");
+
+ if (NULL == benchmark_dir)
+ return;
+
+ if (GNUNET_OK != GNUNET_DISK_directory_create (benchmark_dir))
+ {
+ GNUNET_break (0);
+ return;
+ }
+
+ GNUNET_asprintf (&s, "%s/gnunet-benchmark-ops-%llu-%llu.txt",
+ benchmark_dir,
(unsigned long long) pid,
(unsigned long long) tid);
GNUNET_assert (NULL != fh);
GNUNET_free (s);
- GNUNET_asprintf (&s, "eddsa_sign_count %llu",
- (unsigned long long) bd->eddsa_sign_count);
- GNUNET_assert (GNUNET_SYSERR != GNUNET_DISK_file_write_blocking (fh, s, strlen (s)));
- GNUNET_free (s);
+#define WRITE_BENCHMARK_OP(opname) 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)
+
+ WRITE_BENCHMARK_OP (ecc_ecdh);
+ WRITE_BENCHMARK_OP (ecdh_eddsa);
+ WRITE_BENCHMARK_OP (ecdhe_key_create);
+ WRITE_BENCHMARK_OP (ecdhe_key_get_public);
+ WRITE_BENCHMARK_OP (ecdsa_ecdh);
+ WRITE_BENCHMARK_OP (ecdsa_key_create);
+ WRITE_BENCHMARK_OP (ecdsa_key_get_public);
+ WRITE_BENCHMARK_OP (ecdsa_sign);
+ WRITE_BENCHMARK_OP (ecdsa_verify);
+ WRITE_BENCHMARK_OP (eddsa_ecdh);
+ WRITE_BENCHMARK_OP (eddsa_key_create);
+ WRITE_BENCHMARK_OP (eddsa_key_get_public);
+ WRITE_BENCHMARK_OP (eddsa_sign);
+ WRITE_BENCHMARK_OP (eddsa_verify);
+ WRITE_BENCHMARK_OP (hash);
+ WRITE_BENCHMARK_OP (hash_context_finish);
+ WRITE_BENCHMARK_OP (hash_context_read);
+ WRITE_BENCHMARK_OP (hash_context_start);
+ WRITE_BENCHMARK_OP (hkdf);
+ WRITE_BENCHMARK_OP (rsa_blind);
+ WRITE_BENCHMARK_OP (rsa_private_key_create);
+ WRITE_BENCHMARK_OP (rsa_private_key_get_public);
+ WRITE_BENCHMARK_OP (rsa_sign_blinded);
+ WRITE_BENCHMARK_OP (rsa_unblind);
+ WRITE_BENCHMARK_OP (rsa_verify);
+
+#undef WRITE_BENCHMARK_OP
GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fh));
- GNUNET_asprintf (&s, "gnunet-benchmark-urls-%llu-%llu.txt",
+ GNUNET_asprintf (&s, "%s/gnunet-benchmark-urls-%llu-%llu.txt",
+ benchmark_dir,
(unsigned long long) pid,
(unsigned long long) tid);
* Initialize the thread-local variable key for benchmark data.
*/
static void
-make_key()
+make_key ()
{
(void) pthread_key_create (&key, &thread_destructor);
}
*/
#define MAX_BENCHMARK_URL_LEN 128
+#if ENABLE_BENCHMARK
+#define BENCHMARK_START(opname) \
+ struct GNUNET_TIME_Absolute _benchmark_##opname##_start = GNUNET_TIME_absolute_get ()
+#define BENCHMARK_END(opname) do { \
+ { \
+ struct GNUNET_TIME_Absolute _benchmark_##opname##_end = GNUNET_TIME_absolute_get (); \
+ struct BenchmarkData *bd = get_benchmark_data (); \
+ bd->opname##_count++; \
+ bd->opname##_time = \
+ GNUNET_TIME_relative_add (bd->opname##_time, \
+ GNUNET_TIME_absolute_get_difference (_benchmark_##opname##_start, \
+ _benchmark_##opname##_end)); \
+ } \
+} while (0)
+#else
+#define BENCHMARK_START(opname) do { } while (0)
+#define BENCHMARK_END(opname) do { } while (0)
+#endif
+
/**
* Struct for benchmark data for one URL.
struct GNUNET_TIME_Relative time_min;
};
+#define GNUNET_DECLARE_BENCHMARK_OP(opname) \
+ uint64_t opname##_count; \
+ struct GNUNET_TIME_Relative opname##_time
+
/**
* Thread-local struct for benchmarking data.
*/
struct BenchmarkData
{
- /**
- * Number of eddsa_sign operations.
- */
- uint64_t eddsa_sign_count;
-
- /**
- * Time spent in eddsa_sign.
- */
- struct GNUNET_TIME_Relative eddsa_sign_time;
+ GNUNET_DECLARE_BENCHMARK_OP (ecc_ecdh);
+ GNUNET_DECLARE_BENCHMARK_OP (ecdh_eddsa);
+ GNUNET_DECLARE_BENCHMARK_OP (ecdhe_key_create);
+ GNUNET_DECLARE_BENCHMARK_OP (ecdhe_key_get_public);
+ GNUNET_DECLARE_BENCHMARK_OP (ecdsa_ecdh);
+ GNUNET_DECLARE_BENCHMARK_OP (ecdsa_key_create);
+ GNUNET_DECLARE_BENCHMARK_OP (ecdsa_key_get_public);
+ GNUNET_DECLARE_BENCHMARK_OP (ecdsa_sign);
+ GNUNET_DECLARE_BENCHMARK_OP (ecdsa_verify);
+ GNUNET_DECLARE_BENCHMARK_OP (eddsa_ecdh);
+ GNUNET_DECLARE_BENCHMARK_OP (eddsa_key_create);
+ GNUNET_DECLARE_BENCHMARK_OP (eddsa_key_get_public);
+ GNUNET_DECLARE_BENCHMARK_OP (eddsa_sign);
+ GNUNET_DECLARE_BENCHMARK_OP (eddsa_verify);
+ GNUNET_DECLARE_BENCHMARK_OP (hash);
+ GNUNET_DECLARE_BENCHMARK_OP (hash_context_finish);
+ GNUNET_DECLARE_BENCHMARK_OP (hash_context_read);
+ GNUNET_DECLARE_BENCHMARK_OP (hash_context_start);
+ GNUNET_DECLARE_BENCHMARK_OP (hkdf);
+ GNUNET_DECLARE_BENCHMARK_OP (rsa_blind);
+ GNUNET_DECLARE_BENCHMARK_OP (rsa_private_key_create);
+ GNUNET_DECLARE_BENCHMARK_OP (rsa_private_key_get_public);
+ GNUNET_DECLARE_BENCHMARK_OP (rsa_sign_blinded);
+ GNUNET_DECLARE_BENCHMARK_OP (rsa_unblind);
+ GNUNET_DECLARE_BENCHMARK_OP (rsa_verify);
struct UrlRequestData *urd;
unsigned int urd_capacity;
};
+#undef GNUNET_DECLARE_BENCHMARK_OP
+
/**
* Acquire the benchmark data for the current thread, allocate if necessary.
gcry_ctx_t ctx;
gcry_mpi_t q;
+ BENCHMARK_START (ecdsa_key_get_public);
+
sexp = decode_private_ecdsa_key (priv);
GNUNET_assert (NULL != sexp);
GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof (pub->q_y), q);
gcry_mpi_release (q);
gcry_ctx_release (ctx);
+
+ BENCHMARK_END (ecdsa_key_get_public);
}
gcry_ctx_t ctx;
gcry_mpi_t q;
+ BENCHMARK_START (eddsa_key_get_public);
+
sexp = decode_private_eddsa_key (priv);
GNUNET_assert (NULL != sexp);
GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof (pub->q_y), q);
gcry_mpi_release (q);
gcry_ctx_release (ctx);
+
+ BENCHMARK_END (eddsa_key_get_public);
}
gcry_ctx_t ctx;
gcry_mpi_t q;
+ BENCHMARK_START (ecdhe_key_get_public);
+
sexp = decode_private_ecdhe_key (priv);
GNUNET_assert (NULL != sexp);
GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof (pub->q_y), q);
gcry_mpi_release (q);
gcry_ctx_release (ctx);
+
+ BENCHMARK_END (ecdhe_key_get_public);
}
gcry_mpi_t d;
int rc;
+ BENCHMARK_START (ecdhe_key_create);
+
/* NOTE: For libgcrypt >= 1.7, we do not need the 'eddsa' flag here,
but should also be harmless. For libgcrypt < 1.7, using 'eddsa'
disables an expensive key testing routine. We do not want to run
gcry_sexp_release (priv_sexp);
GNUNET_CRYPTO_mpi_print_unsigned (pk->d, sizeof (pk->d), d);
gcry_mpi_release (d);
+
+ BENCHMARK_END (ecdhe_key_create);
+
return GNUNET_OK;
}
gcry_mpi_t d;
int rc;
+ BENCHMARK_START (ecdsa_key_create);
+
if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
"(genkey(ecc(curve \"" CURVE "\")"
"(flags)))")))
priv = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof (priv->d), d);
gcry_mpi_release (d);
+
+ BENCHMARK_END (ecdsa_key_create);
+
return priv;
}
gcry_mpi_t d;
int rc;
+ BENCHMARK_START (eddsa_key_create);
+
#if CRYPTO_BUG
again:
#endif
}
#endif
+ BENCHMARK_END (eddsa_key_create);
+
return priv;
}
int rc;
gcry_mpi_t rs[2];
+ BENCHMARK_START (ecdsa_sign);
+
priv_sexp = decode_private_ecdsa_key (priv);
data = data_to_ecdsa_value (purpose);
if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp)))
GNUNET_CRYPTO_mpi_print_unsigned (sig->s, sizeof (sig->s), rs[1]);
gcry_mpi_release (rs[0]);
gcry_mpi_release (rs[1]);
+
+ BENCHMARK_END (ecdsa_sign);
+
return GNUNET_OK;
}
int rc;
gcry_mpi_t rs[2];
-#if ENABLE_BENCHMARK
- struct BenchmarkData *bd = get_benchmark_data ();
- bd->eddsa_sign_count++;
-#endif
+ BENCHMARK_START (eddsa_sign);
priv_sexp = decode_private_eddsa_key (priv);
data = data_to_eddsa_value (purpose);
GNUNET_CRYPTO_mpi_print_unsigned (sig->s, sizeof (sig->s), rs[1]);
gcry_mpi_release (rs[0]);
gcry_mpi_release (rs[1]);
+
+ BENCHMARK_END (eddsa_sign);
+
return GNUNET_OK;
}
gcry_sexp_t pub_sexpr;
int rc;
+ BENCHMARK_START (ecdsa_verify);
+
if (purpose != ntohl (validate->purpose))
return GNUNET_SYSERR; /* purpose mismatch */
LOG (GNUNET_ERROR_TYPE_INFO,
_("ECDSA signature verification failed at %s:%d: %s\n"), __FILE__,
__LINE__, gcry_strerror (rc));
+ BENCHMARK_END (ecdsa_verify);
return GNUNET_SYSERR;
}
+ BENCHMARK_END (ecdsa_verify);
return GNUNET_OK;
}
gcry_sexp_t pub_sexpr;
int rc;
+ BENCHMARK_START (eddsa_verify);
+
if (purpose != ntohl (validate->purpose))
return GNUNET_SYSERR; /* purpose mismatch */
LOG (GNUNET_ERROR_TYPE_INFO,
_("EdDSA signature verification failed at %s:%d: %s\n"), __FILE__,
__LINE__, gcry_strerror (rc));
+ BENCHMARK_END (eddsa_verify);
return GNUNET_SYSERR;
}
+ BENCHMARK_END (eddsa_verify);
return GNUNET_OK;
}
unsigned char xbuf[256 / 8];
size_t rsize;
+ BENCHMARK_START (ecc_ecdh);
+
/* first, extract the q = dP value from the public key */
if (0 != gcry_sexp_build (&pub_sexpr, NULL,
"(public-key(ecc(curve " CURVE ")(q %b)))",
rsize,
key_material);
gcry_mpi_release (result_x);
+ BENCHMARK_END (ecc_ecdh);
return GNUNET_OK;
}
gcry_sexp_t pub_sexpr;
int ret;
+ BENCHMARK_START (eddsa_ecdh);
+
/* first, extract the q = dP value from the public key */
if (0 != gcry_sexp_build (&pub_sexpr, NULL,
"(public-key(ecc(curve " CURVE ")(q %b)))",
key_material);
gcry_mpi_point_release (result);
gcry_ctx_release (ctx);
+ BENCHMARK_END (eddsa_ecdh);
return ret;
}
gcry_sexp_t pub_sexpr;
int ret;
+ BENCHMARK_START (ecdsa_ecdh);
+
/* first, extract the q = dP value from the public key */
if (0 != gcry_sexp_build (&pub_sexpr, NULL,
"(public-key(ecc(curve " CURVE ")(q %b)))",
key_material);
gcry_mpi_point_release (result);
gcry_ctx_release (ctx);
+ BENCHMARK_END (ecdsa_ecdh);
return ret;
}
gcry_sexp_t pub_sexpr;
int ret;
+ BENCHMARK_START (ecdh_eddsa);
+
/* first, extract the q = dP value from the public key */
if (0 != gcry_sexp_build (&pub_sexpr, NULL,
"(public-key(ecc(curve " CURVE ")(q %b)))",
key_material);
gcry_mpi_point_release (result);
gcry_ctx_release (ctx);
+ BENCHMARK_END (ecdh_eddsa);
return ret;
}
#include "platform.h"
#include "gnunet_crypto_lib.h"
#include "gnunet_strings_lib.h"
+#include "benchmark.h"
#include <gcrypt.h>
#define LOG(kind,...) GNUNET_log_from (kind, "util-crypto-hash", __VA_ARGS__)
size_t size,
struct GNUNET_HashCode *ret)
{
+ BENCHMARK_START (hash);
gcry_md_hash_buffer (GCRY_MD_SHA512, ret, block, size);
+ BENCHMARK_END (hash);
}
{
struct GNUNET_HashContext *hc;
+ BENCHMARK_START (hash_context_start);
+
hc = GNUNET_new (struct GNUNET_HashContext);
GNUNET_assert (0 ==
gcry_md_open (&hc->hd,
GCRY_MD_SHA512,
0));
+
+ BENCHMARK_END (hash_context_start);
+
return hc;
}
const void *buf,
size_t size)
{
+ BENCHMARK_START (hash_context_read);
gcry_md_write (hc->hd, buf, size);
+ BENCHMARK_END (hash_context_read);
}
{
const void *res = gcry_md_read (hc->hd, 0);
+ BENCHMARK_START (hash_context_finish);
+
GNUNET_assert (NULL != res);
if (NULL != r_hash)
GNUNET_memcpy (r_hash,
res,
sizeof (struct GNUNET_HashCode));
GNUNET_CRYPTO_hash_context_abort (hc);
+ BENCHMARK_END (hash_context_finish);
}
#if GNUNET_BUILD
#include "platform.h"
+#include "benchmark.h"
#include "gnunet_crypto_lib.h"
#else
#define GNUNET_NO 0
size_t ctx_len;
va_list args;
+ BENCHMARK_START (hkdf);
+
if (0 == k)
return GNUNET_SYSERR;
if (GPG_ERR_NO_ERROR !=
hkdf_ok:
gcry_md_close (xtr);
gcry_md_close (prf);
+ BENCHMARK_END (hkdf);
return ret;
}
#include "platform.h"
#include <gcrypt.h>
#include "gnunet_crypto_lib.h"
+#include "benchmark.h"
#define LOG(kind,...) GNUNET_log_from (kind, "util-crypto-rsa", __VA_ARGS__)
gcry_sexp_t s_key;
gcry_sexp_t s_keyparam;
+ BENCHMARK_START (rsa_private_key_create);
+
GNUNET_assert (0 ==
gcry_sexp_build (&s_keyparam,
NULL,
#endif
ret = GNUNET_new (struct GNUNET_CRYPTO_RsaPrivateKey);
ret->sexp = s_key;
+ BENCHMARK_END (rsa_private_key_create);
return ret;
}
int rc;
gcry_sexp_t result;
+ BENCHMARK_START (rsa_private_key_get_public);
+
rc = key_from_sexp (ne, priv->sexp, "public-key", "ne");
if (0 != rc)
rc = key_from_sexp (ne, priv->sexp, "private-key", "ne");
gcry_mpi_release (ne[1]);
pub = GNUNET_new (struct GNUNET_CRYPTO_RsaPublicKey);
pub->sexp = result;
+ BENCHMARK_END (rsa_private_key_get_public);
return pub;
}
gcry_mpi_t data_r_e;
int ret;
+ BENCHMARK_START (rsa_blind);
+
GNUNET_assert (buf != NULL && buf_size != NULL);
ret = key_from_sexp (ne, pkey->sexp, "public-key", "ne");
if (0 != ret)
gcry_mpi_release (data_r_e);
return GNUNET_YES;
+ BENCHMARK_END (rsa_blind);
+
rsa_gcd_validate_failure:
/* We know the RSA key is malicious here, so warn the wallet. */
/* GNUNET_break_op (0); */
gcry_mpi_t v = NULL;
struct GNUNET_CRYPTO_RsaSignature *sig;
+ BENCHMARK_START (rsa_sign_blinded);
+
GNUNET_assert (0 ==
gcry_mpi_scan (&v,
GCRYMPI_FMT_USG,
sig = rsa_sign_mpi (key, v);
gcry_mpi_release (v);
+ BENCHMARK_END (rsa_sign_blinded);
return sig;
}
int ret;
struct GNUNET_CRYPTO_RsaSignature *sret;
+ BENCHMARK_START (rsa_unblind);
+
ret = key_from_sexp (&n, pkey->sexp, "public-key", "n");
if (0 != ret)
ret = key_from_sexp (&n, pkey->sexp, "rsa", "n");
"(sig-val (rsa (s %M)))",
ubsig));
gcry_mpi_release (ubsig);
+ BENCHMARK_END (rsa_unblind);
return sret;
}
gcry_mpi_t r;
int rc;
+ BENCHMARK_START (rsa_verify);
+
r = rsa_full_domain_hash (pkey, hash);
if (NULL == r) {
GNUNET_break_op (0);
__LINE__,
gcry_strerror (rc));
return GNUNET_SYSERR;
+ BENCHMARK_END (rsa_verify);
}
+ BENCHMARK_END (rsa_verify);
return GNUNET_OK;
}