diff --git a/Makefile b/Makefile index dd0eae8..3480bf1 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -CFLAGS=-lm -g -Wall -O2 +CFLAGS=-lm -g -Wall -O3 -mavx2 .PHONY := gen_data main diff --git a/src/repetition_tester.c b/src/repetition_tester.c index 04af939..6f66684 100644 --- a/src/repetition_tester.c +++ b/src/repetition_tester.c @@ -1,5 +1,6 @@ #include #include +#include #include "rprof.h" enum tester_state { @@ -23,6 +24,7 @@ struct repetition_tester { uint64_t test_running_time; uint64_t test_running_bytes; + uint64_t test_running_page_faults; }; struct repetition_results { @@ -30,6 +32,10 @@ struct repetition_results { uint64_t total_time; uint64_t min_time; uint64_t max_time; + + uint64_t total_page_faults; + uint64_t min_page_faults; + uint64_t max_page_faults; }; typedef void (*test_cb)(struct repetition_tester*, void *user); @@ -44,7 +50,7 @@ void repetition_tester_error(struct repetition_tester *tester, char *message) { printf("Error during repetition: %s\n", message); } -void print_repetition_time(char *label, float cpu_time, uint64_t bytes, uint64_t cpu_freq) { +void print_repetition_time(char *label, float cpu_time, uint64_t bytes, uint64_t page_faults, uint64_t cpu_freq) { printf("%s: %.0f", label, cpu_time); if (cpu_freq) { float seconds_time = (float)cpu_time/(float)cpu_freq; @@ -55,7 +61,23 @@ void print_repetition_time(char *label, float cpu_time, uint64_t bytes, uint64_t float bandwidth = bytes / (gigabyte * seconds_time); printf(" at %fgb/s", bandwidth); } + } + if (page_faults) { + printf(" PF: %lu", page_faults); + if (bytes) { + printf(" (%.3fkb/fault)", ((float)bytes)/(page_faults * 1024)); + } + } +} + +uint64_t read_page_faults() { + // NOTE: ru_minflt the number of page faults serviced without any I/O activity. + // ru_majflt the number of page faults serviced that required I/O activity. + struct rusage usage = {}; + getrusage(RUSAGE_SELF, &usage); + int Result = usage.ru_minflt + usage.ru_majflt; + return Result; } bool repetition_tester_continue(struct repetition_tester *tester, struct repetition_results *results) { @@ -88,15 +110,20 @@ bool repetition_tester_continue(struct repetition_tester *tester, struct repetit if (tester->show_current_min) { printf("\r"); - print_repetition_time("Min", tester->test_running_time, tester->test_running_bytes, tester->cpu_freq); + print_repetition_time("Min", tester->test_running_time, tester->test_running_bytes, 0, tester->cpu_freq); fflush(stdout); } } + results->total_page_faults += tester->test_running_page_faults; + results->min_page_faults = MIN(results->min_page_faults, tester->test_running_page_faults); + results->max_page_faults = MAX(results->max_page_faults, tester->test_running_page_faults); + tester->opened_blocks = 0; tester->closed_blocks = 0; tester->test_running_bytes = 0; tester->test_running_time = 0; + tester->test_running_page_faults = 0; uint64_t time_since_last_find = (now - tester->last_found_min_time); if ((time_since_last_find / tester->cpu_freq) >= tester->testing_timeout) { @@ -117,6 +144,9 @@ int repetition_test_run(struct repetition_tester *tester, uint64_t expected_byte results->max_time = 0; results->test_count = 0; results->total_time = 0; + results->max_page_faults = 0; + results->min_page_faults = UINT64_MAX; + results->total_page_faults = 0; while (repetition_tester_continue(tester, results)) { cb(tester, user); @@ -134,15 +164,16 @@ int repetition_test_run(struct repetition_tester *tester, uint64_t expected_byte } 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); + print_repetition_time("Min", results->min_time, tester->expected_byte_count, results->min_page_faults, tester->cpu_freq); printf("\n"); - print_repetition_time("Max", results->max_time, tester->expected_byte_count, tester->cpu_freq); + print_repetition_time("Max", results->max_time, tester->expected_byte_count, results->max_page_faults, 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); + uint64_t avg_page_faults = results->total_page_faults/results->test_count; + print_repetition_time("Avg", avg_time, tester->expected_byte_count, avg_page_faults, tester->cpu_freq); printf("\n"); } } @@ -150,11 +181,13 @@ void print_repetition_results(struct repetition_tester *tester, struct repetitio void repetition_time_start(struct repetition_tester *tester) { tester->opened_blocks++; tester->test_running_time -= rprof_read_cpu_timer(); + tester->test_running_page_faults -= read_page_faults(); } void repetition_time_end(struct repetition_tester *tester) { tester->closed_blocks++; tester->test_running_time += rprof_read_cpu_timer(); + tester->test_running_page_faults += read_page_faults(); } void repetition_count_bytes(struct repetition_tester *tester, int bytes) { diff --git a/src/tests.c b/src/tests.c index 165a2de..1291196 100644 --- a/src/tests.c +++ b/src/tests.c @@ -47,6 +47,23 @@ void handle_buffer_free(struct test_params *params) { } } +void test_write_bytes(struct repetition_tester *tester, void *user) +{ + struct test_params *params = user; + + handle_buffer_malloc(params); + + repetition_time_start(tester); + for (uint64_t i = 0; i < params->byte_count; ++i) { + params->buffer[i] = (uint8_t)i; + } + repetition_time_end(tester); + + repetition_count_bytes(tester, params->byte_count); + + handle_buffer_free(params); +} + void test_fread(struct repetition_tester *tester, void *user) { struct test_params *params = user; @@ -108,12 +125,15 @@ int main() char *filename = "data_10000000.json"; uint64_t file_size = get_file_size(filename); + printf("File size: %lu\n", file_size); struct testcase cases[] = { - { .name = "read inner malloc", .cb = test_read, .inner_malloc = true }, - { .name = "read outer malloc", .cb = test_read, .inner_malloc = false }, - { .name = "fread inner malloc", .cb = test_fread, .inner_malloc = true }, - { .name = "fread outer malloc", .cb = test_fread, .inner_malloc = false }, + { .name = "write bytes", .cb = test_write_bytes, .inner_malloc = false }, + { .name = "write bytes + malloc", .cb = test_write_bytes, .inner_malloc = true }, + { .name = "read", .cb = test_read, .inner_malloc = false }, + { .name = "read + malloc", .cb = test_read, .inner_malloc = true }, + { .name = "fread", .cb = test_fread, .inner_malloc = false }, + { .name = "fread + malloc", .cb = test_fread, .inner_malloc = true }, }; struct repetition_results results = { 0 }; @@ -133,7 +153,6 @@ int main() .inner_malloc = testcase->inner_malloc }; - if (repetition_test_run(&tester, file_size, &results, testcase->cb, ¶ms)) { return -1; } @@ -147,5 +166,7 @@ int main() } } + printf("page faults: %lu\n", read_page_faults()); + return 0; }