660 lines
16 KiB
C++
660 lines
16 KiB
C++
#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)
|
|
|
|
extern "C" void mov_all_bytes_asm(char *buffer, u64 size);
|
|
extern "C" void nop_all_bytes_asm(u64 size);
|
|
extern "C" void nop_1x3_all_bytes_asm(u64 size);
|
|
extern "C" void nop_1x9_all_bytes_asm(u64 size);
|
|
extern "C" void inc_all_bytes_asm(u64 size);
|
|
extern "C" void dec_all_bytes_asm(u64 size);
|
|
extern "C" void align64_loop(u64 size);
|
|
extern "C" void align1_loop(u64 size);
|
|
extern "C" void align15_loop(u64 size);
|
|
extern "C" void align31_loop(u64 size);
|
|
extern "C" void align63_loop(u64 size);
|
|
extern "C" void align75_loop(u64 size);
|
|
extern "C" void align90_loop(u64 size);
|
|
extern "C" void align112_loop(u64 size);
|
|
extern "C" void rat_add(u64 size);
|
|
extern "C" void rat_mov_add(u64 size);
|
|
|
|
void test_fread(reptester *tester, alloc_type type);
|
|
void test_read(reptester *tester, alloc_type type);
|
|
void test_write(reptester *tester, alloc_type type);
|
|
void test_write_mov_all_bytes_asm(reptester *tester, alloc_type type);
|
|
void test_write_nop_all_bytes_asm(reptester *tester, alloc_type type);
|
|
void test_write_nop_1x3_all_bytes_asm(reptester *tester, alloc_type type);
|
|
void test_write_nop_1x9_all_bytes_asm(reptester *tester, alloc_type type);
|
|
void test_write_inc_all_bytes_asm(reptester *tester, alloc_type type);
|
|
void test_write_dec_all_bytes_asm(reptester *tester, alloc_type type);
|
|
void test_align64_loop(reptester *tester, alloc_type type);
|
|
void test_align1_loop(reptester *tester, alloc_type type);
|
|
void test_align15_loop(reptester *tester, alloc_type type);
|
|
void test_align31_loop(reptester *tester, alloc_type type);
|
|
void test_align63_loop(reptester *tester, alloc_type type);
|
|
void test_align75_loop(reptester *tester, alloc_type type);
|
|
void test_align90_loop(reptester *tester, alloc_type type);
|
|
void test_align112_loop(reptester *tester, alloc_type type);
|
|
void test_rat_add(reptester *tester, alloc_type type);
|
|
void test_rat_mov_add(reptester *tester, alloc_type type);
|
|
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 out 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_time
|
|
0, // max_time
|
|
0, // avg_time
|
|
0, // total_time
|
|
},
|
|
{
|
|
0, // min_faults
|
|
0, // max_faults
|
|
0, // avg_faults
|
|
0, // total_bytes
|
|
0, // total_faults
|
|
},
|
|
{}, // results
|
|
};
|
|
// clang-format on
|
|
|
|
FILE *fp = fopen(tester.params.filename, "rb");
|
|
if (!fp) {
|
|
return -1;
|
|
}
|
|
|
|
func_data funcs[] = {
|
|
// {{"WRITE", "WRITE WITH MALLOC"}, test_write},
|
|
// {{"WRITE MOV ASM", "WRITE MOV ASM WITH MALLOC"},
|
|
// test_write_mov_all_bytes_asm},
|
|
// {{"WRITE NOP ASM", "WRITE NOP ASM WITH MALLOC"},
|
|
// test_write_nop_all_bytes_asm},
|
|
// {{"WRITE NOP 1x3 ASM", "WRITE NOP 1x3 ASM WITH MALLOC"},
|
|
// test_write_nop_1x3_all_bytes_asm},
|
|
// {{"WRITE NOP 1x9 ASM", "WRITE NOP 1x9 ASM WITH MALLOC"},
|
|
// test_write_nop_1x9_all_bytes_asm},
|
|
// {{"WRITE INC ASM", "WRITE INC ASM WITH MALLOC"},
|
|
// test_write_inc_all_bytes_asm},
|
|
// {{"WRITE DEC ASM", "WRITE DEC ASM WITH MALLOC"},
|
|
// test_write_dec_all_bytes_asm},
|
|
// {{"READ", "READ WITH MALLOC"}, test_read},
|
|
// {{"FREAD", "FREAD WITH MALLOC"}, test_fread},
|
|
// {{"ALIGN 64", "ALIGN 64 WITH MALLOC"}, test_align64_loop},
|
|
// {{"ALIGN 1", "ALIGN 1 WITH MALLOC"}, test_align1_loop},
|
|
// {{"ALIGN 15", "ALIGN 15 WITH MALLOC"}, test_align15_loop},
|
|
// {{"ALIGN 31", "ALIGN 31 WITH MALLOC"}, test_align31_loop},
|
|
// {{"ALIGN 63", "ALIGN 63 WITH MALLOC"}, test_align63_loop},
|
|
// {{"ALIGN 75", "ALIGN 75 WITH MALLOC"}, test_align75_loop},
|
|
// {{"ALIGN 90", "ALIGN 90 WITH MALLOC"}, test_align90_loop},
|
|
// {{"ALIGN 112", "ALIGN 112 WITH MALLOC"}, test_align112_loop},
|
|
// {{"ALIGN 112", "ALIGN 112 WITH MALLOC"}, test_align112_loop},
|
|
{{"RAT ADD", "RAT ADD WITH MALLOC"}, test_rat_add},
|
|
{{"RAT MOV ADD", "RAT MOV ADD WITH MALLOC"}, test_rat_mov_add},
|
|
};
|
|
|
|
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) {
|
|
for (u64 k = 0; k < COUNT_ALLOC_TYPE; ++k) {
|
|
run_func_test(&tester, funcs[j].func, funcs[j].names[k], (alloc_type)k);
|
|
}
|
|
}
|
|
}
|
|
|
|
fclose(fp);
|
|
|
|
free(tester.params.buffer);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void test_fread(reptester *tester, alloc_type type) {
|
|
FILE *fp = fopen(tester->params.filename, "rb");
|
|
if (!fp) {
|
|
return;
|
|
}
|
|
|
|
u64 start = read_cpu_timer();
|
|
u64 fault_count_start = page_fault_count();
|
|
|
|
handle_alloc(tester, type);
|
|
|
|
u64 obj_count = fread(tester->params.buffer, tester->params.read_size,
|
|
tester->params.read_count, fp);
|
|
|
|
u64 fault_count_end = page_fault_count();
|
|
u64 end = read_cpu_timer();
|
|
|
|
u64 bytes_read = obj_count * tester->params.read_size;
|
|
|
|
u64 read_time = end - start;
|
|
u64 page_faults = fault_count_end - fault_count_start;
|
|
|
|
tester->results = {
|
|
bytes_read,
|
|
read_time,
|
|
page_faults,
|
|
};
|
|
|
|
handle_free(tester, type);
|
|
|
|
fclose(fp);
|
|
}
|
|
|
|
void test_read(reptester *tester, alloc_type type) {
|
|
FILE *fp = fopen(tester->params.filename, "rb");
|
|
if (!fp) {
|
|
return;
|
|
}
|
|
|
|
u64 start = read_cpu_timer();
|
|
u64 fault_count_start = page_fault_count();
|
|
|
|
handle_alloc(tester, type);
|
|
|
|
i32 fd = fileno(fp);
|
|
|
|
u64 bytes_read = read(fd, tester->params.buffer,
|
|
tester->params.read_size * tester->params.read_count);
|
|
|
|
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 = {
|
|
bytes_read,
|
|
read_time,
|
|
page_faults,
|
|
};
|
|
|
|
handle_free(tester, type);
|
|
|
|
fclose(fp);
|
|
}
|
|
|
|
void write_to_all_bytes(char *buffer, u64 size) {
|
|
for (u64 i = 0; i < size; ++i) {
|
|
buffer[i] = i;
|
|
}
|
|
}
|
|
|
|
void test_write(reptester *tester, alloc_type type) {
|
|
u64 start = read_cpu_timer();
|
|
u64 fault_count_start = page_fault_count();
|
|
|
|
handle_alloc(tester, type);
|
|
|
|
u64 total_size = tester->params.read_size * tester->params.read_count;
|
|
|
|
write_to_all_bytes(tester->params.buffer, total_size);
|
|
|
|
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);
|
|
}
|
|
|
|
void test_write_mov_all_bytes_asm(reptester *tester, alloc_type type) {
|
|
u64 start = read_cpu_timer();
|
|
u64 fault_count_start = page_fault_count();
|
|
|
|
handle_alloc(tester, type);
|
|
|
|
u64 total_size = tester->params.read_size * tester->params.read_count;
|
|
|
|
mov_all_bytes_asm(tester->params.buffer, total_size);
|
|
|
|
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);
|
|
}
|
|
|
|
void test_write_nop_all_bytes_asm(reptester *tester, alloc_type type) {
|
|
u64 start = read_cpu_timer();
|
|
u64 fault_count_start = page_fault_count();
|
|
|
|
handle_alloc(tester, type);
|
|
|
|
u64 total_size = tester->params.read_size * tester->params.read_count;
|
|
|
|
nop_all_bytes_asm(total_size);
|
|
|
|
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);
|
|
}
|
|
|
|
void test_write_nop_1x3_all_bytes_asm(reptester *tester, alloc_type type) {
|
|
u64 start = read_cpu_timer();
|
|
u64 fault_count_start = page_fault_count();
|
|
|
|
handle_alloc(tester, type);
|
|
|
|
u64 total_size = tester->params.read_size * tester->params.read_count;
|
|
|
|
nop_1x3_all_bytes_asm(total_size);
|
|
|
|
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);
|
|
}
|
|
|
|
void test_write_nop_1x9_all_bytes_asm(reptester *tester, alloc_type type) {
|
|
u64 start = read_cpu_timer();
|
|
u64 fault_count_start = page_fault_count();
|
|
|
|
handle_alloc(tester, type);
|
|
|
|
u64 total_size = tester->params.read_size * tester->params.read_count;
|
|
|
|
nop_1x9_all_bytes_asm(total_size);
|
|
|
|
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);
|
|
}
|
|
|
|
void test_write_inc_all_bytes_asm(reptester *tester, alloc_type type) {
|
|
u64 start = read_cpu_timer();
|
|
u64 fault_count_start = page_fault_count();
|
|
|
|
handle_alloc(tester, type);
|
|
|
|
u64 total_size = tester->params.read_size * tester->params.read_count;
|
|
|
|
inc_all_bytes_asm(total_size);
|
|
|
|
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);
|
|
}
|
|
|
|
void test_write_dec_all_bytes_asm(reptester *tester, alloc_type type) {
|
|
u64 start = read_cpu_timer();
|
|
u64 fault_count_start = page_fault_count();
|
|
|
|
handle_alloc(tester, type);
|
|
|
|
u64 total_size = tester->params.read_size * tester->params.read_count;
|
|
|
|
dec_all_bytes_asm(total_size);
|
|
|
|
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);
|
|
}
|
|
|
|
void test_align64_loop(reptester *tester, alloc_type type) {
|
|
u64 start = read_cpu_timer();
|
|
u64 fault_count_start = page_fault_count();
|
|
|
|
handle_alloc(tester, type);
|
|
|
|
u64 total_size = tester->params.read_size * tester->params.read_count;
|
|
|
|
align64_loop(total_size);
|
|
|
|
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);
|
|
}
|
|
|
|
void test_align1_loop(reptester *tester, alloc_type type) {
|
|
u64 start = read_cpu_timer();
|
|
u64 fault_count_start = page_fault_count();
|
|
|
|
handle_alloc(tester, type);
|
|
|
|
u64 total_size = tester->params.read_size * tester->params.read_count;
|
|
|
|
align1_loop(total_size);
|
|
|
|
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);
|
|
}
|
|
|
|
void test_align15_loop(reptester *tester, alloc_type type) {
|
|
u64 start = read_cpu_timer();
|
|
u64 fault_count_start = page_fault_count();
|
|
|
|
handle_alloc(tester, type);
|
|
|
|
u64 total_size = tester->params.read_size * tester->params.read_count;
|
|
|
|
align15_loop(total_size);
|
|
|
|
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);
|
|
}
|
|
|
|
void test_align31_loop(reptester *tester, alloc_type type) {
|
|
u64 start = read_cpu_timer();
|
|
u64 fault_count_start = page_fault_count();
|
|
|
|
handle_alloc(tester, type);
|
|
|
|
u64 total_size = tester->params.read_size * tester->params.read_count;
|
|
|
|
align31_loop(total_size);
|
|
|
|
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);
|
|
}
|
|
|
|
void test_align63_loop(reptester *tester, alloc_type type) {
|
|
u64 start = read_cpu_timer();
|
|
u64 fault_count_start = page_fault_count();
|
|
|
|
handle_alloc(tester, type);
|
|
|
|
u64 total_size = tester->params.read_size * tester->params.read_count;
|
|
|
|
align63_loop(total_size);
|
|
|
|
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);
|
|
}
|
|
|
|
void test_align75_loop(reptester *tester, alloc_type type) {
|
|
|
|
u64 start = read_cpu_timer();
|
|
u64 fault_count_start = page_fault_count();
|
|
|
|
handle_alloc(tester, type);
|
|
|
|
u64 total_size = tester->params.read_size * tester->params.read_count;
|
|
|
|
align75_loop(total_size);
|
|
|
|
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);
|
|
}
|
|
|
|
void test_align90_loop(reptester *tester, alloc_type type) {
|
|
|
|
u64 start = read_cpu_timer();
|
|
u64 fault_count_start = page_fault_count();
|
|
|
|
handle_alloc(tester, type);
|
|
|
|
u64 total_size = tester->params.read_size * tester->params.read_count;
|
|
|
|
align90_loop(total_size);
|
|
|
|
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);
|
|
}
|
|
|
|
void test_align112_loop(reptester *tester, alloc_type type) {
|
|
u64 start = read_cpu_timer();
|
|
u64 fault_count_start = page_fault_count();
|
|
|
|
handle_alloc(tester, type);
|
|
|
|
u64 total_size = tester->params.read_size * tester->params.read_count;
|
|
|
|
align112_loop(total_size);
|
|
|
|
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);
|
|
}
|
|
|
|
void test_rat_add(reptester *tester, alloc_type type) {
|
|
u64 start = read_cpu_timer();
|
|
u64 fault_count_start = page_fault_count();
|
|
|
|
handle_alloc(tester, type);
|
|
|
|
u64 total_size = tester->params.read_size * tester->params.read_count;
|
|
|
|
rat_add(total_size);
|
|
|
|
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);
|
|
}
|
|
|
|
void test_rat_mov_add(reptester *tester, alloc_type type) {
|
|
u64 start = read_cpu_timer();
|
|
u64 fault_count_start = page_fault_count();
|
|
|
|
handle_alloc(tester, type);
|
|
|
|
u64 total_size = tester->params.read_size * tester->params.read_count;
|
|
|
|
rat_mov_add(total_size);
|
|
|
|
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) {
|
|
if (!fp) {
|
|
return 0;
|
|
}
|
|
|
|
fseek(fp, 0, SEEK_END);
|
|
|
|
u64 length = ftell(fp);
|
|
|
|
fseek(fp, 0, SEEK_SET);
|
|
|
|
return length;
|
|
}
|