1
0

add malloc_read and write_all_bytes tests

This commit is contained in:
Rokas Puzonas 2024-02-15 19:47:10 +02:00
parent 4720f092ae
commit da9af2ff49
8 changed files with 242 additions and 29 deletions

View File

@ -1,4 +1,4 @@
CFLAGS=-lm -g -Wall -O0
CFLAGS=-lm -g -Wall -O1
build/main: src/main.c src/repetition_tester.c build/nop_loop.o src/rprof.h
mkdir -p build

View File

@ -9,7 +9,9 @@
#include "rprof.h"
#include "main_read_file.c"
#include "main_write_bytes.c"
#include "main_write_bytes_asm.c"
#include "main_write_all_bytes.c"
#include "main_malloc_read.c"
int main(int argc, char **argv) {
if (argc < 2) {
@ -19,8 +21,10 @@ int main(int argc, char **argv) {
char *test_name = argv[1];
if (!strncmp(test_name, "write_bytes", sizeof("write_bytes"))) {
return main_test_write_bytes();
if (!strncmp(test_name, "write_bytes_asm", sizeof("write_bytes_asm"))) {
return main_test_write_bytes_asm();
} else if (!strncmp(test_name, "write_all_bytes", sizeof("write_bytes"))) {
return main_test_write_all_bytes();
} else if (!strncmp(test_name, "read_file", sizeof("read_file"))) {
if (argc < 3) {
printf("Usage: %s read_file <filename>\n", argv[0]);
@ -28,6 +32,13 @@ int main(int argc, char **argv) {
}
return main_test_read_file(argv[2]);
} else if (!strncmp(test_name, "malloc_read", sizeof("malloc_read"))) {
if (argc < 3) {
printf("Usage: %s malloc_read <filename>\n", argv[0]);
return -1;
}
return main_test_malloc_read(argv[2]);
} else {
printf("ERROR: Unknown test case '%s'\n", test_name);
return -1;

114
src/main_malloc_read.c Normal file
View File

@ -0,0 +1,114 @@
#include <sys/stat.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include "utils.c"
#include "repetition_tester.c"
static void read_malloc_file_with_fread(bool should_alloc, struct repetitor *repetitor, uint8_t *buffer, uint64_t buffer_size, char *filename) {
alloc_buffer(should_alloc, &buffer, buffer_size);
FILE *file = fopen(filename, "r");
uint64_t read_amount = 0;
while (read_amount < buffer_size) {
repetitor_measure_start(repetitor);
int result = fread(&buffer[read_amount], 1, buffer_size - read_amount, file);
repetitor_measure_stop(repetitor, result > 0 ? result : 0);
if (result <= 0) {
printf("ERROR: Failed to read from file\n");
break;
}
read_amount += result;
}
fclose(file);
free_buffer(should_alloc, buffer);
}
static void read_malloc_file_with_read(bool should_alloc, struct repetitor *repetitor, uint8_t *buffer, uint64_t buffer_size, char *filename) {
alloc_buffer(should_alloc, &buffer, buffer_size);
int file = open(filename, O_RDONLY);
uint64_t read_amount = 0;
while (read_amount < buffer_size) {
repetitor_measure_start(repetitor);
int result = read(file, &buffer[read_amount], buffer_size - read_amount);
repetitor_measure_stop(repetitor, result > 0 ? result : 0);
if (result <= 0) {
printf("ERROR: Failed to read from file\n");
break;
}
read_amount += result;
}
close(file);
free_buffer(should_alloc, buffer);
}
int main_test_malloc_read(char *filename) {
typedef void (*read_file_b)(bool should_alloc, struct repetitor *repetitor, uint8_t *buffer, uint64_t buffer_size, char *filename);
struct testcase {
char *name;
read_file_b cb;
};
struct testcase cases[] = {
{ .name = "read()", .cb = read_malloc_file_with_fread },
{ .name = "fread()", .cb = read_malloc_file_with_read },
};
struct repetitor repetitor = {};
repetitor_init(&repetitor);
printf("CPU Frequency: %ldHz (~%.2fGHz)\n", repetitor.cpu_freq, (float)repetitor.cpu_freq/(1000*1000*1000));
uint64_t file_size = get_file_size(filename);
uint8_t *buffer = malloc(sizeof(uint8_t) * file_size);
memset(buffer, 0, file_size); // Touch memory, so OS would be forced to page in the memory
while (repeat_cycle_times(&repetitor, 3)) {
for (int i = 0; i < ARRAY_LEN(cases); i++) {
struct testcase *testcase = &cases[i];
// With malloc
{
repetitor_clear(&repetitor);
while (repetitor_repeat(&repetitor, 3)) {
repetitor_start(&repetitor);
testcase->cb(true, &repetitor, buffer, file_size, filename);
repetitor_stop(&repetitor);
}
char label[256];
snprintf(label, sizeof(label), "%s + malloc", testcase->name);
repetitor_print_results_label(&repetitor, label);
}
// Without malloc
{
repetitor_clear(&repetitor);
while (repetitor_repeat(&repetitor, 1)) {
repetitor_start(&repetitor);
testcase->cb(false, &repetitor, buffer, file_size, filename);
repetitor_stop(&repetitor);
}
char label[256];
snprintf(label, sizeof(label), "%s + no malloc", testcase->name);
repetitor_print_results_label(&repetitor, label);
}
}
}
return 0;
}

View File

@ -3,20 +3,17 @@
#include <unistd.h>
#include <fcntl.h>
#include "utils.c"
#include "repetition_tester.c"
uint64_t get_file_size(const char *filename) {
struct stat result;
stat(filename, &result);
return result.st_size;
}
void read_file_with_fread(uint8_t *buffer, uint64_t buffer_size, char *filename) {
void read_file_with_fread(struct repetitor *repetitor, uint8_t *buffer, uint64_t buffer_size, char *filename) {
FILE *file = fopen(filename, "r");
uint64_t read_amount = 0;
while (read_amount < buffer_size) {
repetitor_measure_start(repetitor);
int result = fread(&buffer[read_amount], 1, buffer_size - read_amount, file);
repetitor_measure_stop(repetitor, result > 0 ? result : 0);
if (result <= 0) {
printf("ERROR: Failed to read from file\n");
@ -29,12 +26,14 @@ void read_file_with_fread(uint8_t *buffer, uint64_t buffer_size, char *filename)
fclose(file);
}
void read_file_with_read(uint8_t *buffer, uint64_t buffer_size, char *filename) {
void read_file_with_read(struct repetitor *repetitor, uint8_t *buffer, uint64_t buffer_size, char *filename) {
int file = open(filename, O_RDONLY);
uint64_t read_amount = 0;
while (read_amount < buffer_size) {
repetitor_measure_start(repetitor);
int result = read(file, &buffer[read_amount], buffer_size - read_amount);
repetitor_measure_stop(repetitor, result > 0 ? result : 0);
if (result <= 0) {
printf("ERROR: Failed to read from file\n");
@ -48,7 +47,7 @@ void read_file_with_read(uint8_t *buffer, uint64_t buffer_size, char *filename)
}
int main_test_read_file(char *filename) {
typedef void (*read_file_b)(uint8_t *buffer, uint64_t buffer_size, char *filename);
typedef void (*read_file_b)(struct repetitor *repetitor, uint8_t *buffer, uint64_t buffer_size, char *filename);
struct testcase {
char *name;
read_file_b cb;
@ -66,15 +65,15 @@ int main_test_read_file(char *filename) {
uint64_t file_size = get_file_size(filename);
uint8_t *buffer = malloc(sizeof(uint8_t) * file_size);
while (repeat_forever(&repetitor)) {
while (repeat_cycle_times(&repetitor, 3)) {
for (int i = 0; i < ARRAY_LEN(cases); i++) {
struct testcase *testcase = &cases[i];
repetitor_clear(&repetitor);
while (repetitor_repeat(&repetitor, 1)) {
repetitor_start(&repetitor);
testcase->cb(buffer, file_size, filename);
repetitor_stop(&repetitor, file_size);
testcase->cb(&repetitor, buffer, file_size, filename);
repetitor_stop(&repetitor);
}
repetitor_print_results_label(&repetitor, testcase->name);

View File

@ -0,0 +1,42 @@
#include "repetition_tester.c"
#include "utils.c"
static void test_write_to_all_bytes(struct repetitor *repetitor, uint8_t *buffer, uint64_t buffer_size, bool should_alloc) {
repetitor_clear(repetitor);
while (repetitor_repeat(repetitor, 2)) {
repetitor_start(repetitor);
alloc_buffer(should_alloc, &buffer, buffer_size);
repetitor_measure_start(repetitor);
for (int i = 0; i < buffer_size; i++) {
buffer[i] = (uint8_t)i;
}
repetitor_measure_stop(repetitor, buffer_size);
free_buffer(should_alloc, buffer);
repetitor_stop(repetitor);
}
}
int main_test_write_all_bytes() {
struct repetitor repetitor = {};
repetitor_init(&repetitor);
printf("CPU Frequency: %ldHz (~%.2fGHz)\n", repetitor.cpu_freq, (float)repetitor.cpu_freq/(1000*1000*1000));
uint64_t byte_count = 4096 * (1024 * 8);
uint8_t *buffer = malloc(sizeof(uint8_t) * byte_count);
memset(buffer, 0, byte_count); // Touch memory, so OS would be forced to page in the memory
while (repeat_cycle_forever(&repetitor)) {
test_write_to_all_bytes(&repetitor, buffer, byte_count, false);
repetitor_print_results_label(&repetitor, "write to all bytes + no malloc");
test_write_to_all_bytes(&repetitor, buffer, byte_count, true);
repetitor_print_results_label(&repetitor, "write to all bytes + malloc");
}
return 0;
}

View File

@ -1,7 +1,7 @@
#include "repetition_tester.c"
#include "nop_loop.h"
int main_test_write_bytes() {
int main_test_write_bytes_asm() {
typedef void (*write_bytes_cb)(uint8_t *buffer, uint64_t byte_count);
struct testcase {
char *name;
@ -27,8 +27,10 @@ int main_test_write_bytes() {
while (repetitor_repeat(&repetitor, 2)) {
repetitor_start(&repetitor);
repetitor_measure_start(&repetitor);
testcase->cb(buffer, byte_count);
repetitor_stop(&repetitor, byte_count);
repetitor_measure_stop(&repetitor, byte_count);
repetitor_stop(&repetitor);
}
repetitor_print_results_label(&repetitor, testcase->name);

View File

@ -12,6 +12,7 @@ struct repetitor {
uint64_t repetition_count;
uint64_t time_taken;
uint64_t page_faults;
uint64_t byte_count;
uint64_t total_time_taken;
uint64_t total_page_faults;
@ -42,6 +43,7 @@ void repetitor_clear(struct repetitor *repetitor) {
repetitor->time_taken = 0;
repetitor->page_faults = 0;
repetitor->byte_count = 0;
repetitor->total_page_faults = 0;
repetitor->total_time_taken = 0;
@ -64,38 +66,44 @@ void repetitor_init(struct repetitor *repetitor) {
repetitor_clear(repetitor);
}
void repetitor_start(struct repetitor *repetitor) {
void repetitor_measure_start(struct repetitor *repetitor) {
repetitor->page_faults -= read_page_faults();
repetitor->time_taken -= rprof_read_cpu_timer();
}
void repetitor_stop(struct repetitor *repetitor, uint64_t byte_count) {
void repetitor_measure_stop(struct repetitor *repetitor, int byte_count) {
repetitor->time_taken += rprof_read_cpu_timer();
repetitor->page_faults += read_page_faults();
repetitor->byte_count += byte_count;
}
void repetitor_start(struct repetitor *repetitor) {
repetitor->time_taken = 0;
repetitor->page_faults = 0;
repetitor->byte_count = 0;
}
void repetitor_stop(struct repetitor *repetitor) {
if (repetitor->repetition_count == 0) {
repetitor->max_time_taken = repetitor->time_taken;
repetitor->max_page_faults = repetitor->page_faults;
repetitor->max_byte_count = byte_count;
repetitor->max_byte_count = repetitor->byte_count;
repetitor->min_time_taken = repetitor->time_taken;
repetitor->min_page_faults = repetitor->page_faults;
repetitor->min_byte_count = byte_count;
repetitor->min_byte_count = repetitor->byte_count;
} else {
repetitor->max_time_taken = max_uint64(repetitor->max_time_taken, repetitor->time_taken);
repetitor->max_page_faults = max_uint64(repetitor->max_page_faults, repetitor->page_faults);
repetitor->max_byte_count = max_uint64(repetitor->max_byte_count, byte_count);
repetitor->max_byte_count = max_uint64(repetitor->max_byte_count, repetitor->byte_count);
repetitor->min_time_taken = min_uint64(repetitor->min_time_taken, repetitor->time_taken);
repetitor->min_page_faults = min_uint64(repetitor->min_page_faults, repetitor->page_faults);
repetitor->min_byte_count = min_uint64(repetitor->min_byte_count, byte_count);
repetitor->min_byte_count = min_uint64(repetitor->min_byte_count, repetitor->byte_count);
}
repetitor->total_time_taken += repetitor->time_taken;
repetitor->total_page_faults += repetitor->page_faults;
repetitor->total_byte_count += byte_count;
repetitor->total_byte_count += repetitor->byte_count;
repetitor->repetition_count += 1;
repetitor->time_taken = 0;
repetitor->page_faults = 0;
}
bool repetitor_repeat(struct repetitor *repetitor, float timeout_seconds) {
@ -121,7 +129,17 @@ bool repetitor_repeat(struct repetitor *repetitor, float timeout_seconds) {
return true;
}
bool repeat_forever(struct repetitor *repetitor) {
bool repeat_cycle_forever(struct repetitor *repetitor) {
repetitor->repeat_cycle += 1;
printf("======= Cycle %ld ================================\n", repetitor->repeat_cycle);
return true;
}
bool repeat_cycle_times(struct repetitor *repetitor, int max_cycles) {
if (repetitor->repeat_cycle >= max_cycles) {
return false;
}
repetitor->repeat_cycle += 1;
printf("======= Cycle %ld ================================\n", repetitor->repeat_cycle);
return true;

27
src/utils.c Normal file
View File

@ -0,0 +1,27 @@
#ifndef UTILS_
#define UTILS_
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <sys/stat.h>
uint64_t get_file_size(const char *filename) {
struct stat result;
stat(filename, &result);
return result.st_size;
}
static void alloc_buffer(bool should_alloc, uint8_t **buffer, uint64_t buffer_size) {
if (should_alloc) {
*buffer = malloc(sizeof(uint8_t) * buffer_size);
}
}
static void free_buffer(bool should_alloc, uint8_t *buffer) {
if (should_alloc) {
free(buffer);
}
}
#endif //UTILS_