diff options
Diffstat (limited to 'src/argon2-impl-select.c')
-rw-r--r-- | src/argon2-impl-select.c | 93 |
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); +} |