2022-06-29 21:29:15 +02:00
|
|
|
#include "../lib/helper.h"
|
2022-06-29 10:50:55 +02:00
|
|
|
|
|
|
|
int stringToInt(char *string) {
|
|
|
|
char *leftover = "";
|
|
|
|
errno = 0;
|
|
|
|
int x = strtold(string, &leftover);
|
|
|
|
if (*leftover != '\0' || leftover == string) {
|
|
|
|
errno = EINVAL;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (errno == ERANGE) {
|
|
|
|
printf("Number is too large or too small!\n");
|
|
|
|
errno = EINVAL;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
errno = 0;
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
|
|
|
|
void help(char *progname) {
|
2022-07-07 17:45:33 +02:00
|
|
|
fprintf(stdout,
|
|
|
|
"Usage: %s [options...] <file>\n\
|
|
|
|
-V, --version <version> use a specific implementation\n\
|
|
|
|
-B, --benchmark [repetitons] benchmark the execution and optionally repeat it\n\
|
|
|
|
-T, --test run self-test. If set, no file is needed\n\
|
2022-07-18 13:16:28 +02:00
|
|
|
-h, --help print this help page\n\
|
|
|
|
\n\
|
|
|
|
<version> is an integer between 0 and 4.\n\
|
|
|
|
0: naive implementation\n\
|
|
|
|
1: optimized implementation\n\
|
|
|
|
2: memory efficient implementation\n\
|
|
|
|
3: threaded implementation\n\
|
2022-07-20 17:46:35 +02:00
|
|
|
4: reference implementation\n"
|
|
|
|
#ifdef MD2_DETAILED_BENCHMARK
|
|
|
|
"\n\
|
|
|
|
\n\033[1;33mWARNING: Detailed benchmarking is enabled. This will show detailed benchmaring results\n\
|
|
|
|
after each hash calculation but will decrease the overall performance.\033[0m"
|
|
|
|
#endif // MD2_DETAILED_BENCHMARK
|
|
|
|
"\n",
|
2022-07-07 17:45:33 +02:00
|
|
|
progname);
|
2022-06-29 10:50:55 +02:00
|
|
|
}
|
|
|
|
|
2022-06-29 11:12:35 +02:00
|
|
|
enum argumentParseResult parseArguments(int argc, char **argv,
|
|
|
|
struct configuration *c) {
|
|
|
|
if (c == NULL) {
|
2022-06-29 10:50:55 +02:00
|
|
|
return RESULT_EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
c->implementationToUse = 0;
|
2022-07-07 17:45:33 +02:00
|
|
|
c->doBenchmark = false;
|
2022-06-29 10:50:55 +02:00
|
|
|
c->benchmarkingCycles = 1;
|
2022-07-07 17:45:33 +02:00
|
|
|
c->runTests = false;
|
2022-06-29 10:50:55 +02:00
|
|
|
|
|
|
|
int opt;
|
|
|
|
|
|
|
|
while (1) {
|
2022-07-07 17:45:33 +02:00
|
|
|
static struct option longOptions[] = {
|
|
|
|
{"version", required_argument, NULL, 'V'},
|
|
|
|
{"benchmark", optional_argument, NULL, 'B'},
|
|
|
|
{"test", optional_argument, NULL, 'T'},
|
|
|
|
{"help", no_argument, NULL, 'h'},
|
|
|
|
{NULL}};
|
2022-06-29 10:50:55 +02:00
|
|
|
int longOptionIndex = 0;
|
|
|
|
|
2022-07-07 17:45:33 +02:00
|
|
|
opt = getopt_long(argc, argv, "V:B::Th", longOptions, &longOptionIndex);
|
2022-06-29 10:50:55 +02:00
|
|
|
|
|
|
|
if (-1 == opt) break;
|
|
|
|
|
|
|
|
switch (opt) {
|
|
|
|
case 'B':
|
2022-07-07 17:45:33 +02:00
|
|
|
c->doBenchmark = true;
|
2022-06-29 10:50:55 +02:00
|
|
|
if (optarg != NULL) {
|
|
|
|
c->benchmarkingCycles = stringToInt(optarg);
|
|
|
|
if (errno == 0) break;
|
|
|
|
fprintf(stderr,
|
|
|
|
"%s: invalid argument, has to be int -- 'B' got '%s'\n",
|
|
|
|
argv[0], optarg);
|
|
|
|
return RESULT_EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'V':
|
|
|
|
c->implementationToUse = stringToInt(optarg);
|
|
|
|
if (errno == 0) break;
|
|
|
|
fprintf(stderr, "%s: invalid argument, has to be int -- 'V' got '%s'\n",
|
|
|
|
argv[0], optarg);
|
|
|
|
return RESULT_EXIT_FAILURE;
|
|
|
|
|
2022-07-07 17:45:33 +02:00
|
|
|
case 'T':
|
|
|
|
c->runTests = true;
|
|
|
|
break;
|
|
|
|
|
2022-06-29 10:50:55 +02:00
|
|
|
case 'h':
|
|
|
|
help(argv[0]);
|
|
|
|
return RESULT_EXIT_SUCCESS;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return RESULT_EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (argc > optind) {
|
|
|
|
c->filename = argv[optind];
|
2022-07-07 17:45:33 +02:00
|
|
|
} else if (!c->runTests) {
|
2022-06-29 10:50:55 +02:00
|
|
|
fprintf(stderr, "%s: missing poisional argument -- 'file'\n", argv[0]);
|
|
|
|
return RESULT_EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return RESULT_OK;
|
2022-07-06 20:35:10 +02:00
|
|
|
}
|
|
|
|
|
2022-07-20 17:46:35 +02:00
|
|
|
double current_time() {
|
2022-07-06 20:35:10 +02:00
|
|
|
struct timespec t;
|
|
|
|
clock_gettime(CLOCK_MONOTONIC, &t);
|
|
|
|
return t.tv_sec + t.tv_nsec * 1e-9;
|
|
|
|
}
|
|
|
|
|
2022-07-07 17:15:41 +02:00
|
|
|
double run_benchmark(unsigned cycles, md2_hash_func func, size_t len,
|
|
|
|
uint8_t *buf, uint8_t *out) {
|
2022-07-06 20:35:10 +02:00
|
|
|
double start = current_time();
|
2022-07-07 17:15:41 +02:00
|
|
|
for (; cycles > 0; cycles--) {
|
|
|
|
func(len, buf, out);
|
|
|
|
}
|
2022-07-06 20:35:10 +02:00
|
|
|
double end = current_time();
|
|
|
|
|
|
|
|
return end - start;
|
2022-06-29 10:50:55 +02:00
|
|
|
}
|