aboutsummaryrefslogtreecommitdiffstats
path: root/src/argon2-impl-select.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/argon2-impl-select.c')
-rw-r--r--src/argon2-impl-select.c93
1 files changed, 93 insertions, 0 deletions
diff --git a/src/argon2-impl-select.c b/src/argon2-impl-select.c
new file mode 100644
index 0000000..b4c18a7
--- /dev/null
+++ b/src/argon2-impl-select.c
@@ -0,0 +1,93 @@
+#include <time.h>
+#include <string.h>
+
+#include "argon2-impl-select.h"
+
+#include "argon2.h"
+
+#define BENCH_SAMPLES 512
+#define BENCH_MEM_BLOCKS 512
+
+static argon2_impl selected_argon_impl = {
+ "(default)", NULL, fill_segment_default
+};
+
+/* the benchmark routine is not thread-safe, so we can use a global var here: */
+static block memory[BENCH_MEM_BLOCKS];
+
+static uint64_t benchmark_impl(const argon2_impl *impl) {
+ clock_t time;
+ unsigned int i;
+ uint64_t bench;
+ argon2_instance_t instance;
+ argon2_position_t pos;
+
+ memset(memory, 0, sizeof(memory));
+
+ instance.version = ARGON2_VERSION_NUMBER;
+ instance.memory = memory;
+ instance.passes = 1;
+ instance.memory_blocks = BENCH_MEM_BLOCKS;
+ instance.segment_length = BENCH_MEM_BLOCKS / ARGON2_SYNC_POINTS;
+ instance.lane_length = instance.segment_length * ARGON2_SYNC_POINTS;
+ instance.lanes = 1;
+ instance.threads = 1;
+ instance.type = Argon2_i;
+
+ pos.lane = 0;
+ pos.pass = 0;
+ pos.slice = 0;
+ pos.index = 0;
+
+ /* warm-up cache: */
+ impl->fill_segment(&instance, pos);
+
+ /* OK, now measure: */
+ bench = 0;
+ time = clock();
+ for (i = 0; i < BENCH_SAMPLES; i++) {
+ impl->fill_segment(&instance, pos);
+ }
+ time = clock() - time;
+ bench = (uint64_t)time;
+ return bench;
+}
+
+static void select_impl(FILE *out, const char *prefix)
+{
+ argon2_impl_list impls;
+ unsigned int i;
+ const argon2_impl *best_impl = NULL;
+ uint64_t best_bench = UINT_MAX;
+
+ argon2_get_impl_list(&impls);
+
+ for (i = 0; i < impls.count; i++) {
+ const argon2_impl *impl = &impls.entries[i];
+ uint64_t bench;
+
+ bench = benchmark_impl(impl);
+
+ if (bench < best_bench) {
+ best_bench = bench;
+ best_impl = impl;
+ }
+ }
+
+ if (best_impl != NULL) {
+ selected_argon_impl = *best_impl;
+ }
+}
+
+void fill_segment(const argon2_instance_t *instance, argon2_position_t position)
+{
+ selected_argon_impl.fill_segment(instance, position);
+}
+
+void argon2_select_impl(FILE *out, const char *prefix)
+{
+ if (prefix == NULL) {
+ prefix = "";
+ }
+ select_impl(out, prefix);
+}