add repetition tester
This commit is contained in:
parent
3b8986e008
commit
828de96add
4
Makefile
4
Makefile
@ -14,6 +14,10 @@ build/main: src/main.c src/json_parser.c src/rprof.h
|
||||
mkdir -p build
|
||||
gcc -o build/main src/main.c $(CFLAGS)
|
||||
|
||||
build/test: src/tests.c src/repetition_tester.c
|
||||
mkdir -p build
|
||||
gcc -o build/test src/tests.c $(CFLAGS)
|
||||
|
||||
build/guess_cpu_speed: src/guess_cpu_speed.c src/timer.c
|
||||
mkdir -p build
|
||||
gcc -o build/guess_cpu_speed src/guess_cpu_speed.c $(CFLAGS)
|
||||
|
1
compile_flags.txt
Normal file
1
compile_flags.txt
Normal file
@ -0,0 +1 @@
|
||||
-DRPROF_IMPLEMENTATION
|
@ -5,13 +5,14 @@
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
|
||||
#define RPROF_IMPLEMENTATION
|
||||
|
||||
#include "harvensine_compute.h"
|
||||
#include "rprof.h"
|
||||
#include "json_parser.c"
|
||||
#include "harvensine_formula.c"
|
||||
|
||||
#define RPROF_IMPLEMENTATION
|
||||
#include "rprof.h"
|
||||
|
||||
struct point_pair {
|
||||
f64 x0;
|
||||
f64 y0;
|
||||
|
162
src/repetition_tester.c
Normal file
162
src/repetition_tester.c
Normal file
@ -0,0 +1,162 @@
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include "rprof.h"
|
||||
|
||||
enum tester_state {
|
||||
STATE_UNKNOWN,
|
||||
STATE_RUNNING,
|
||||
STATE_FINISHED,
|
||||
STATE_ERROR
|
||||
};
|
||||
|
||||
struct repetition_tester {
|
||||
enum tester_state state;
|
||||
|
||||
uint64_t cpu_freq;
|
||||
uint32_t testing_timeout;
|
||||
uint64_t expected_byte_count;
|
||||
uint64_t last_found_min_time;
|
||||
bool show_current_min;
|
||||
|
||||
uint32_t closed_blocks;
|
||||
uint32_t opened_blocks;
|
||||
|
||||
uint64_t test_running_time;
|
||||
uint64_t test_running_bytes;
|
||||
};
|
||||
|
||||
struct repetition_results {
|
||||
uint64_t test_count;
|
||||
uint64_t total_time;
|
||||
uint64_t min_time;
|
||||
uint64_t max_time;
|
||||
};
|
||||
|
||||
typedef void (*test_cb)(struct repetition_tester*, void *user);
|
||||
|
||||
void repetition_tester_init(struct repetition_tester *tester) {
|
||||
tester->cpu_freq = rprof_get_cpu_timer_hz(100);
|
||||
tester->testing_timeout = 10;
|
||||
}
|
||||
|
||||
void repetition_tester_error(struct repetition_tester *tester, char *message) {
|
||||
tester->state = STATE_ERROR;
|
||||
printf("Error during repetition: %s\n", message);
|
||||
}
|
||||
|
||||
void print_repetition_time(char *label, float cpu_time, uint64_t bytes, uint64_t cpu_freq) {
|
||||
printf("%s: %.0f", label, cpu_time);
|
||||
if (cpu_freq) {
|
||||
float seconds_time = (float)cpu_time/(float)cpu_freq;
|
||||
printf(" (%fms)", seconds_time*1000.0);
|
||||
|
||||
if (bytes) {
|
||||
float gigabyte = 1024 * 1024 * 1024;
|
||||
float bandwidth = bytes / (gigabyte * seconds_time);
|
||||
printf(" at %fgb/s", bandwidth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool repetition_tester_continue(struct repetition_tester *tester, struct repetition_results *results) {
|
||||
if (tester->state != STATE_RUNNING) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (tester->opened_blocks == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (tester->opened_blocks != tester->closed_blocks) {
|
||||
repetition_tester_error(tester, "Closed blocks doesn't match opened blocks");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (tester->expected_byte_count != tester->test_running_bytes) {
|
||||
repetition_tester_error(tester, "Processed byte coutn doesn't match");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t now = rprof_read_cpu_timer();
|
||||
|
||||
results->test_count += 1;
|
||||
results->total_time += tester->test_running_time;
|
||||
results->max_time = MAX(results->max_time, tester->test_running_time);
|
||||
if (tester->test_running_time < results->min_time) {
|
||||
results->min_time = tester->test_running_time;
|
||||
tester->last_found_min_time = now;
|
||||
|
||||
if (tester->show_current_min) {
|
||||
printf("\r");
|
||||
print_repetition_time("Min", tester->test_running_time, tester->test_running_bytes, tester->cpu_freq);
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
tester->opened_blocks = 0;
|
||||
tester->closed_blocks = 0;
|
||||
tester->test_running_bytes = 0;
|
||||
tester->test_running_time = 0;
|
||||
|
||||
uint64_t time_since_last_find = (now - tester->last_found_min_time);
|
||||
if ((time_since_last_find / tester->cpu_freq) >= tester->testing_timeout) {
|
||||
tester->state = STATE_FINISHED;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int repetition_test_run(struct repetition_tester *tester, uint64_t expected_byte_count, struct repetition_results *results, test_cb cb, void *user) {
|
||||
memset(results, 0, sizeof(struct repetition_results));
|
||||
tester->state = STATE_RUNNING;
|
||||
tester->expected_byte_count = expected_byte_count;
|
||||
tester->last_found_min_time = rprof_read_cpu_timer();
|
||||
|
||||
results->min_time = UINT64_MAX;
|
||||
results->max_time = 0;
|
||||
results->test_count = 0;
|
||||
results->total_time = 0;
|
||||
|
||||
while (repetition_tester_continue(tester, results)) {
|
||||
cb(tester, user);
|
||||
}
|
||||
|
||||
if (tester->show_current_min) {
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
if (tester->state == STATE_ERROR) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void print_repetition_results(struct repetition_tester *tester, struct repetition_results *results) {
|
||||
print_repetition_time("Min", results->min_time, tester->expected_byte_count, tester->cpu_freq);
|
||||
printf("\n");
|
||||
|
||||
print_repetition_time("Max", results->max_time, tester->expected_byte_count, tester->cpu_freq);
|
||||
printf("\n");
|
||||
|
||||
if (results->test_count) {
|
||||
uint64_t avg_time = results->total_time/results->test_count;
|
||||
print_repetition_time("Avg", avg_time, tester->expected_byte_count, tester->cpu_freq);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
void repetition_time_start(struct repetition_tester *tester) {
|
||||
tester->opened_blocks++;
|
||||
tester->test_running_time -= rprof_read_cpu_timer();
|
||||
}
|
||||
|
||||
void repetition_time_end(struct repetition_tester *tester) {
|
||||
tester->closed_blocks++;
|
||||
tester->test_running_time += rprof_read_cpu_timer();
|
||||
}
|
||||
|
||||
void repetition_count_bytes(struct repetition_tester *tester, int bytes) {
|
||||
tester->test_running_bytes += bytes;
|
||||
}
|
@ -76,6 +76,7 @@ void rprof_output(prof_sort_cmp_cb sort_cb);
|
||||
#define RPROF_START_BYTES(label, bytes) rprof_start(__COUNTER__, label, bytes)
|
||||
#define RPROF_STOP() rprof_stop()
|
||||
|
||||
#define RPROF_IMPLEMENTATION
|
||||
#ifdef RPROF_IMPLEMENTATION
|
||||
|
||||
// ------------------------ CPU Timing -------------------------
|
||||
|
119
src/tests.c
Normal file
119
src/tests.c
Normal file
@ -0,0 +1,119 @@
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "repetition_tester.c"
|
||||
|
||||
#define RPROF_IMPLEMENTATION
|
||||
#include "rprof.h"
|
||||
|
||||
#define ARRAY_LEN(x) (sizeof(x)/sizeof(x[0]))
|
||||
|
||||
size_t get_file_size(char *filename)
|
||||
{
|
||||
FILE *f = fopen(filename, "r");
|
||||
if (f == NULL) { return 0; }
|
||||
|
||||
fseek(f, 0, SEEK_END);
|
||||
size_t size = ftell(f);
|
||||
|
||||
fclose(f);
|
||||
return size;
|
||||
}
|
||||
|
||||
struct test_params {
|
||||
char *filename;
|
||||
uint8_t *buffer;
|
||||
uint64_t byte_count;
|
||||
};
|
||||
|
||||
struct testcase {
|
||||
char *name;
|
||||
test_cb cb;
|
||||
};
|
||||
|
||||
void test_fread(struct repetition_tester *tester, void *user)
|
||||
{
|
||||
struct test_params *params = user;
|
||||
FILE *f = fopen(params->filename, "r");
|
||||
if (f == NULL) {
|
||||
repetition_tester_error(tester, "Failed to open file");
|
||||
return;
|
||||
}
|
||||
|
||||
repetition_time_start(tester);
|
||||
int result = fread(params->buffer, params->byte_count, 1, f);
|
||||
repetition_time_end(tester);
|
||||
if (result <= 0) {
|
||||
repetition_tester_error(tester, "Failed to read file");
|
||||
goto err;
|
||||
}
|
||||
|
||||
repetition_count_bytes(tester, params->byte_count);
|
||||
|
||||
err:
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
void test_read(struct repetition_tester *tester, void *user)
|
||||
{
|
||||
struct test_params *params = user;
|
||||
int fd = open(params->filename, O_RDONLY);
|
||||
if (fd <= 0) {
|
||||
repetition_tester_error(tester, "Failed to open file");
|
||||
return;
|
||||
}
|
||||
|
||||
repetition_time_start(tester);
|
||||
int result = read(fd, params->buffer, params->byte_count);
|
||||
repetition_time_end(tester);
|
||||
if (result <= 0) {
|
||||
repetition_tester_error(tester, "Failed to read file");
|
||||
goto err;
|
||||
}
|
||||
|
||||
repetition_count_bytes(tester, result);
|
||||
|
||||
err:
|
||||
close(fd);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
struct repetition_tester tester = { 0 };
|
||||
repetition_tester_init(&tester);
|
||||
tester.show_current_min = true;
|
||||
|
||||
char *filename = "data_10000000.json";
|
||||
uint64_t file_size = get_file_size(filename);
|
||||
|
||||
uint8_t *buffer = malloc(sizeof(uint8_t) * file_size);
|
||||
struct test_params params = {
|
||||
.filename = filename,
|
||||
.buffer = buffer,
|
||||
.byte_count = file_size
|
||||
};
|
||||
|
||||
struct testcase cases[] = {
|
||||
{ .name = "fread", .cb = test_fread },
|
||||
{ .name = "read", .cb = test_read },
|
||||
};
|
||||
|
||||
struct repetition_results results = { 0 };
|
||||
while (true) {
|
||||
for (int i = 0; i < ARRAY_LEN(cases); i++) {
|
||||
struct testcase *testcase = &cases[i];
|
||||
|
||||
if (repetition_test_run(&tester, file_size, &results, testcase->cb, ¶ms)) {
|
||||
return -1;
|
||||
}
|
||||
printf("----- %s -----\n", testcase->name);
|
||||
print_repetition_results(&tester, &results);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user