Add page fault stats to repetition tester

This commit is contained in:
Abdelrahman Said 2023-09-23 23:55:46 +01:00
parent dca94a0edf
commit 7ce7101240
3 changed files with 121 additions and 10 deletions

View File

@ -13,6 +13,7 @@ struct reptest_params {
struct reptest_results { struct reptest_results {
u64 bytes_read; u64 bytes_read;
u64 read_time; u64 read_time;
u64 page_faults;
}; };
struct time_stats { struct time_stats {
@ -22,6 +23,14 @@ struct time_stats {
u64 total_time; u64 total_time;
}; };
struct mem_stats {
u64 min_faults;
u64 max_faults;
u64 avg_faults;
u64 total_bytes;
u64 total_faults;
};
struct reptester { struct reptester {
reptest_params params; reptest_params params;
@ -33,6 +42,7 @@ struct reptester {
u64 current_run; u64 current_run;
time_stats tstats; time_stats tstats;
mem_stats mstats;
reptest_results results; reptest_results results;
}; };
@ -55,6 +65,7 @@ void handle_alloc(reptester *tester, alloc_type type);
void handle_free(reptester *tester, alloc_type type); void handle_free(reptester *tester, alloc_type type);
void run_func_test(reptester *tester, reptest_func func, const char *func_name, void run_func_test(reptester *tester, reptest_func func, const char *func_name,
alloc_type type); alloc_type type);
u64 page_fault_count();
void print_results(reptester *tester, const char *name); void print_results(reptester *tester, const char *name);
#endif // !REPTESTER_H #endif // !REPTESTER_H

View File

@ -11,6 +11,7 @@
void test_fread(reptester *tester, alloc_type type); void test_fread(reptester *tester, alloc_type type);
void test_read(reptester *tester, alloc_type type); void test_read(reptester *tester, alloc_type type);
void test_write(reptester *tester, alloc_type type);
u64 get_file_length(FILE *fp); u64 get_file_length(FILE *fp);
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
@ -41,10 +42,17 @@ int main(int argc, char *argv[]) {
1, // current_run 1, // current_run
{ {
UINT64_MAX, // min UINT64_MAX, // min_time
0, // max 0, // max_time
0, // avg 0, // avg_time
0, // total 0, // total_time
},
{
0, // min_faults
0, // max_faults
0, // avg_faults
0, // total_bytes
0, // total_faults
}, },
{}, // results {}, // results
}; };
@ -55,7 +63,8 @@ int main(int argc, char *argv[]) {
return -1; return -1;
} }
func_data funcs[] = {{{"READ", "READ WITH MALLOC"}, test_read}, func_data funcs[] = {{{"WRITE", "WRITE WITH MALLOC"}, test_write},
{{"READ", "READ WITH MALLOC"}, test_read},
{{"FREAD", "FREAD WITH MALLOC"}, test_fread}}; {{"FREAD", "FREAD WITH MALLOC"}, test_fread}};
tester.params.read_size = get_file_length(fp); tester.params.read_size = get_file_length(fp);
@ -87,17 +96,23 @@ void test_fread(reptester *tester, alloc_type type) {
handle_alloc(tester, type); handle_alloc(tester, type);
u64 start = read_cpu_timer(); u64 start = read_cpu_timer();
u64 fault_count_start = page_fault_count();
u64 obj_count = fread(tester->params.buffer, tester->params.read_size, u64 obj_count = fread(tester->params.buffer, tester->params.read_size,
tester->params.read_count, fp); tester->params.read_count, fp);
u64 fault_count_end = page_fault_count();
u64 end = read_cpu_timer(); u64 end = read_cpu_timer();
u64 bytes_read = obj_count * tester->params.read_size; u64 bytes_read = obj_count * tester->params.read_size;
u64 read_time = end - start; u64 read_time = end - start;
u64 page_faults = fault_count_end - fault_count_start;
tester->results = { tester->results = {
bytes_read, bytes_read,
read_time, read_time,
page_faults,
}; };
handle_free(tester, type); handle_free(tester, type);
@ -116,15 +131,21 @@ void test_read(reptester *tester, alloc_type type) {
i32 fd = fileno(fp); i32 fd = fileno(fp);
u64 start = read_cpu_timer(); u64 start = read_cpu_timer();
u64 fault_count_start = page_fault_count();
u64 bytes_read = read(fd, tester->params.buffer, u64 bytes_read = read(fd, tester->params.buffer,
tester->params.read_size * tester->params.read_count); tester->params.read_size * tester->params.read_count);
u64 fault_count_end = page_fault_count();
u64 end = read_cpu_timer(); u64 end = read_cpu_timer();
u64 read_time = end - start; u64 read_time = end - start;
u64 page_faults = fault_count_end - fault_count_start;
tester->results = { tester->results = {
bytes_read, bytes_read,
read_time, read_time,
page_faults,
}; };
handle_free(tester, type); handle_free(tester, type);
@ -132,6 +153,33 @@ void test_read(reptester *tester, alloc_type type) {
fclose(fp); fclose(fp);
} }
void test_write(reptester *tester, alloc_type type) {
handle_alloc(tester, type);
u64 start = read_cpu_timer();
u64 fault_count_start = page_fault_count();
u64 total_size = tester->params.read_size * tester->params.read_count;
for (u64 i = 0; i < total_size; ++i) {
tester->params.buffer[i] = '0';
}
u64 fault_count_end = page_fault_count();
u64 end = read_cpu_timer();
u64 read_time = end - start;
u64 page_faults = fault_count_end - fault_count_start;
tester->results = {
total_size,
read_time,
page_faults,
};
handle_free(tester, type);
}
u64 get_file_length(FILE *fp) { u64 get_file_length(FILE *fp) {
if (!fp) { if (!fp) {
return 0; return 0;

View File

@ -3,6 +3,8 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/resource.h>
#include <sys/time.h>
void handle_alloc(reptester *tester, alloc_type type) { void handle_alloc(reptester *tester, alloc_type type) {
switch (type) { switch (type) {
@ -43,6 +45,13 @@ void run_func_test(reptester *tester, reptest_func func, const char *func_name,
0, // avg_time 0, // avg_time
0, // total_time 0, // total_time
}; };
tester->mstats = {
UINT64_MAX, // min_faults
0, // max_faults
0, // avg_faults
0, // total_bytes
0, // total_faults
};
tester->results = {}; tester->results = {};
char *buffer = NULL; char *buffer = NULL;
@ -66,12 +75,22 @@ void run_func_test(reptester *tester, reptest_func func, const char *func_name,
} }
tester->tstats.total_time += tester->results.read_time; tester->tstats.total_time += tester->results.read_time;
tester->mstats.total_bytes += tester->results.bytes_read;
tester->mstats.total_faults += tester->results.page_faults;
if (tester->results.read_time > tester->tstats.max_time) { if (tester->results.read_time > tester->tstats.max_time) {
tester->tstats.max_time = tester->results.read_time; tester->tstats.max_time = tester->results.read_time;
tester->mstats.max_faults = tester->results.page_faults;
} else if (tester->results.read_time < tester->tstats.min_time) { } else if (tester->results.read_time < tester->tstats.min_time) {
tester->test_start_time = read_cpu_timer(); tester->test_start_time = read_cpu_timer();
tester->tstats.min_time = tester->results.read_time; tester->tstats.min_time = tester->results.read_time;
tester->mstats.min_faults = tester->results.page_faults;
}
if (tester->results.page_faults > tester->mstats.max_faults) {
tester->mstats.max_faults = tester->results.page_faults;
} else if (tester->results.page_faults < tester->mstats.min_faults) {
tester->mstats.min_faults = tester->results.page_faults;
} }
tester->test_time_secs = time_in_seconds( tester->test_time_secs = time_in_seconds(
@ -88,24 +107,57 @@ void run_func_test(reptester *tester, reptest_func func, const char *func_name,
print_results(tester, func_name); print_results(tester, func_name);
} }
void print_results(reptester *tester, const char *name) { u64 page_fault_count() {
f64 gb = 1024.0 * 1024.0 * 1024.0; rusage usage;
getrusage(RUSAGE_SELF, &usage);
return usage.ru_minflt + usage.ru_majflt;
}
void print_results(reptester *tester, const char *name) {
f64 kb = 1024.0;
f64 gb = kb * kb * kb;
f64 size_in_kb =
(f64)(tester->params.read_size * tester->params.read_count) / kb;
f64 size_in_gb = f64 size_in_gb =
(f64)(tester->params.read_size * tester->params.read_count) / gb; (f64)(tester->params.read_size * tester->params.read_count) / gb;
u64 run_count = tester->current_run - 1; u64 run_count = tester->current_run - 1;
tester->tstats.avg_time = tester->tstats.total_time / run_count; tester->tstats.avg_time = tester->tstats.total_time / run_count;
tester->mstats.avg_faults = tester->mstats.total_faults / run_count;
printf("\n%s: %lu runs\n", name, run_count); printf("\n%s: %lu runs\n", name, run_count);
printf("MIN: %lu (%fGB/s)\n", tester->tstats.min_time,
printf("MIN: %lu (%fGB/s)", tester->tstats.min_time,
size_in_gb / size_in_gb /
time_in_seconds(tester->tstats.min_time, tester->cpu_freq)); time_in_seconds(tester->tstats.min_time, tester->cpu_freq));
printf("MAX: %lu (%fGB/s)\n", tester->tstats.max_time, if (tester->mstats.min_faults > 0) {
printf(", FAULTS: %lu (%fK/fault)\n", tester->mstats.min_faults,
size_in_kb / tester->mstats.min_faults);
} else {
printf("\n");
}
printf("MAX: %lu (%fGB/s)", tester->tstats.max_time,
size_in_gb / size_in_gb /
time_in_seconds(tester->tstats.max_time, tester->cpu_freq)); time_in_seconds(tester->tstats.max_time, tester->cpu_freq));
printf("AVG: %lu (%fGB/s)\n", tester->tstats.avg_time, if (tester->mstats.max_faults > 0) {
printf(", FAULTS: %lu (%fK/fault)\n", tester->mstats.max_faults,
size_in_kb / tester->mstats.max_faults);
} else {
printf("\n");
}
printf("AVG: %lu (%fGB/s)", tester->tstats.avg_time,
size_in_gb / size_in_gb /
time_in_seconds(tester->tstats.avg_time, tester->cpu_freq)); time_in_seconds(tester->tstats.avg_time, tester->cpu_freq));
if (tester->mstats.avg_faults > 0) {
printf(", FAULTS: %lu (%fK/fault)\n", tester->mstats.avg_faults,
tester->mstats.total_bytes / kb / tester->mstats.avg_faults);
} else {
printf("\n");
}
} }