Basic repetition testing implementation

This commit is contained in:
Abdelrahman Said 2023-09-09 21:25:32 +01:00
parent 1bfc162845
commit 9ddb991b94
3 changed files with 240 additions and 0 deletions

View File

@ -0,0 +1,44 @@
#ifndef REPTESTER_H
#define REPTESTER_H
#include "aliases.h"
struct reptest_params {
const char *filename;
char *buffer;
u64 read_size;
u64 read_count;
};
struct reptest_results {
u64 bytes_read;
u64 read_time;
};
struct reptester {
reptest_params params;
const u64 cpu_freq;
f64 wait_time_secs;
f64 test_time_secs;
u64 test_start_time;
u64 current_run;
u64 min;
u64 max;
u64 avg;
u64 total;
reptest_results results;
};
struct reptest_func {
const char *name;
void (*func)(reptester *tester);
};
void run_func_test(reptester *tester, reptest_func func_obj);
void print_results(reptester *tester, const char *name);
#endif // !REPTESTER_H

View File

@ -0,0 +1,134 @@
#include "aliases.h"
#include "profiler/timer.h"
#include "repetition_testing/reptester.h"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define ARR_LEN(ARR) sizeof(ARR) / sizeof(*ARR)
void test_fread(reptester *tester);
void test_read(reptester *tester);
u64 get_file_length(FILE *fp);
int main(int argc, char *argv[]) {
const char *filename = NULL;
u64 waves = 1;
switch (argc) {
case 3:
waves = atol(argv[2]);
// break left intentionally
case 2:
filename = argv[1];
break;
default:
printf("Usage: reptest FILENAME [WAVE_COUNT]\n");
return -1;
break;
}
// clang-format off
reptester tester = {
{filename, NULL, 0, 0}, // params
get_cpu_freq(500), // cpu_freq
10.0, // wait_time_secs
0.0, // test_time_secs
read_cpu_timer(), // test_start_time
1, // current_run
UINT64_MAX, // min
0, // max
0, // avg
0, // total
{}, // results
};
// clang-format on
FILE *fp = fopen(tester.params.filename, "rb");
if (!fp) {
return -1;
}
reptest_func funcs[] = {{"FREAD", test_fread}, {"READ", test_read}};
tester.params.read_size = get_file_length(fp);
tester.params.read_count = 1;
tester.params.buffer = (char *)malloc(tester.params.read_size + 1);
memset(tester.params.buffer, 0, tester.params.read_size + 1);
for (u64 i = 0; i < waves; ++i) {
for (u64 j = 0; j < ARR_LEN(funcs); ++j) {
run_func_test(&tester, funcs[j]);
}
}
fclose(fp);
free(tester.params.buffer);
return 0;
}
void test_fread(reptester *tester) {
FILE *fp = fopen(tester->params.filename, "rb");
if (!fp) {
return;
}
u64 start = read_cpu_timer();
u64 obj_count = fread(tester->params.buffer, tester->params.read_size,
tester->params.read_count, fp);
u64 end = read_cpu_timer();
u64 bytes_read = obj_count * tester->params.read_size;
u64 read_time = end - start;
tester->results = {
bytes_read,
read_time,
};
fclose(fp);
}
void test_read(reptester *tester) {
FILE *fp = fopen(tester->params.filename, "rb");
if (!fp) {
return;
}
i32 fd = fileno(fp);
u64 start = read_cpu_timer();
u64 bytes_read = read(fd, tester->params.buffer,
tester->params.read_size * tester->params.read_count);
u64 end = read_cpu_timer();
u64 read_time = end - start;
tester->results = {
bytes_read,
read_time,
};
fclose(fp);
}
u64 get_file_length(FILE *fp) {
if (!fp) {
return 0;
}
fseek(fp, 0, SEEK_END);
u64 length = ftell(fp);
fseek(fp, 0, SEEK_SET);
return length;
}

View File

@ -0,0 +1,62 @@
#include "repetition_testing/reptester.h"
#include "profiler/timer.h"
#include <stdio.h>
void run_func_test(reptester *tester, reptest_func func_obj) {
tester->test_start_time = read_cpu_timer();
tester->test_time_secs = 0.0;
tester->current_run = 1;
tester->min = UINT64_MAX;
tester->max = 0;
tester->avg = 0;
tester->total = 0;
tester->results = {};
while (tester->test_time_secs <= tester->wait_time_secs) {
func_obj.func(tester);
if (tester->results.bytes_read <
tester->params.read_size * tester->params.read_count) {
printf("Failed to read the entire file (Total size: %lu, Bytes read: "
"%lu)\n",
tester->params.read_size, tester->results.bytes_read);
return;
}
tester->total += tester->results.read_time;
if (tester->results.read_time > tester->max) {
tester->max = tester->results.read_time;
} else if (tester->results.read_time < tester->min) {
tester->test_start_time = read_cpu_timer();
tester->min = tester->results.read_time;
}
tester->test_time_secs = time_in_seconds(
read_cpu_timer() - tester->test_start_time, tester->cpu_freq);
++(tester->current_run);
}
print_results(tester, func_obj.name);
}
void print_results(reptester *tester, const char *name) {
f64 gb = 1024.0 * 1024.0 * 1024.0;
f64 size_in_gb =
(f64)(tester->params.read_size * tester->params.read_count) / gb;
u64 run_count = tester->current_run - 1;
tester->avg = tester->total / run_count;
printf("\n%s: %lu runs\n", name, run_count);
printf("MIN: %lu (%fGB/s)\n", tester->min,
size_in_gb / time_in_seconds(tester->min, tester->cpu_freq));
printf("MAX: %lu (%fGB/s)\n", tester->max,
size_in_gb / time_in_seconds(tester->max, tester->cpu_freq));
printf("AVG: %lu (%fGB/s)\n", tester->avg,
size_in_gb / time_in_seconds(tester->avg, tester->cpu_freq));
}