add malloc_read and write_all_bytes tests
This commit is contained in:
parent
4720f092ae
commit
da9af2ff49
2
Makefile
2
Makefile
@ -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
|
||||
|
17
src/main.c
17
src/main.c
@ -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
114
src/main_malloc_read.c
Normal 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;
|
||||
}
|
@ -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);
|
||||
|
42
src/main_write_all_bytes.c
Normal file
42
src/main_write_all_bytes.c
Normal 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;
|
||||
}
|
||||
|
@ -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);
|
@ -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
27
src/utils.c
Normal 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_
|
Loading…
Reference in New Issue
Block a user