aos/usr/test/filesystem_performance/main.c

292 lines
6.8 KiB
C

/**
* \file
* \brief file system test application
*/
/*
* Copyright (c) 2016 ETH Zurich.
* All rights reserved.
*
* This file is distributed under the terms in the attached LICENSE file.
* If you do not find this file, copies can be found by writing to:
* ETH Zurich D=INFK, CAB F.78, Universitaetstr. 6, CH-8092 Zurich,
* Attn: Systems Group.
*/
#include <stdio.h>
#include <aos/aos.h>
#include <fs/fs.h>
#include <fs/dirent.h>
#include <drivers/block_driver.h>
#include <aos/deferred.h>
#define MOUNTPOINT "/sdcard"
#define FILENAME "/test.txt"
#define DIRNAME "/tdir"
#define ITERATIONS 100
#define THROUGHPUT_MEASUREMENT_BYTES (10 * PAGE_SIZE)
#define MEASUREMENT_PREAMBLE \
debug_printf("\n-------------------------------\n"); \
debug_printf("Measuring: %s\n", __FUNCTION__);
// #define MEASUREMENT_ENABLED
#ifdef MEASUREMENT_ENABLED
#include <aos/performance.h>
static struct performance_context perf_context;
#define PERF_INIT {perf_init(&perf_context, __FUNCTION__);}
#define PERF_PRINT {perf_print(&perf_context);}
#define PERF_ADD(tag) {perf_add_now(&perf_context, tag);}
#else
#define PERF_INIT
#define PERF_PRINT
#define PERF_ADD(tag)
#endif
__attribute__((__used__))
static void measure_fopen_fclose(void) {
MEASUREMENT_PREAMBLE
char *file = MOUNTPOINT FILENAME;
FILE *f;
int res;
// first we open because it might need to be created
f = fopen(file, "w");
assert(f != NULL);
res = fclose(f);
assert(res == 0);
// measure latency to open multiple times
PERF_INIT
for(size_t i = 0; i < ITERATIONS; ++i) {
PERF_ADD("pre_open")
f = fopen(file, "r");
PERF_ADD("post_open")
assert(f != NULL);
PERF_ADD("pre_close")
res = fclose(f);
PERF_ADD("post_close")
assert(res == 0);
}
PERF_PRINT
}
__attribute__((__used__))
static void measure_fcreate_and_rm_single(void) {
MEASUREMENT_PREAMBLE
char *file = MOUNTPOINT FILENAME;
FILE *f;
int res;
errval_t err;
// make sure the file does not exist
rm(file);
// create and delete a file many times
PERF_INIT
for(size_t i = 0; i < ITERATIONS; ++i) {
PERF_ADD("pre_create")
f = fopen(file, "w");
PERF_ADD("post_create")
assert(f != NULL);
res = fclose(f);
assert(res == 0);
PERF_ADD("pre_rm")
err = rm(file);
PERF_ADD("post_rm")
assert(err_is_ok(err));
}
PERF_PRINT
}
__attribute__((__used__))
static void measure_fcreate_and_rm_many(void) {
MEASUREMENT_PREAMBLE
FILE *f;
int res;
errval_t err;
char name[256] = {0};
// create many files
PERF_INIT
for(size_t i = 0; i < ITERATIONS; ++i) {
snprintf(name, 256, MOUNTPOINT "/%lu.txt", i);
PERF_ADD("pre_create")
f = fopen(name, "w");
PERF_ADD("post_create")
assert(f != NULL);
res = fclose(f);
assert(res == 0);;
}
PERF_PRINT
// delete many files
PERF_INIT
for(size_t i = 0; i < ITERATIONS; ++i) {
snprintf(name, 256, MOUNTPOINT "/%lu.txt", i);
PERF_ADD("pre_rm")
err = rm(name);
PERF_ADD("post_rm")
assert(err_is_ok(err));
}
PERF_PRINT
}
__attribute__((__used__))
static void measure_mkdir_and_rmdir_single(void) {
MEASUREMENT_PREAMBLE
char *dir = MOUNTPOINT DIRNAME;
errval_t err;
// make sure the directory does not exist
rmdir(dir);
// create and delete a directory many times
PERF_INIT
for(size_t i = 0; i < ITERATIONS; ++i) {
PERF_ADD("pre_mkdir")
err = mkdir(dir);
PERF_ADD("post_mkdir")
assert(err_is_ok(err));
PERF_ADD("pre_rmdir")
err = rmdir(dir);
PERF_ADD("post_rmdir")
assert(err_is_ok(err));
}
PERF_PRINT
}
char *much_data[THROUGHPUT_MEASUREMENT_BYTES];
__attribute__((__used__))
static void measure_write_throughput(void) {
MEASUREMENT_PREAMBLE
char *file = MOUNTPOINT FILENAME;
FILE *f;
int res;
// make sure the file does not yet exist
rm(file);
PERF_INIT
for (size_t i = 0; i < ITERATIONS; ++i) {
// we want to create a new file and write a lot of data to it
f = fopen(file, "w");
assert(f != NULL);
PERF_ADD("pre")
size_t written_bytes = fwrite(much_data, 1, THROUGHPUT_MEASUREMENT_BYTES, f);
PERF_ADD("post")
assert(written_bytes == THROUGHPUT_MEASUREMENT_BYTES);
res = fclose(f);
assert(res == 0);
}
PERF_PRINT
}
__attribute__((__used__))
static void measure_read_throughput(void) {
MEASUREMENT_PREAMBLE
char *file = MOUNTPOINT FILENAME;
FILE *f;
// make sure the file exists and contains enough data
f = fopen(file, "w");
assert(f != NULL);
size_t written_bytes = fwrite(much_data, 1, THROUGHPUT_MEASUREMENT_BYTES, f);
assert(written_bytes == THROUGHPUT_MEASUREMENT_BYTES);
assert(fclose(f) == 0);
f = fopen(file, "r");
assert(f != NULL);
PERF_INIT
for (size_t i = 0; i < ITERATIONS; ++i) {
rewind(f);
PERF_ADD("pre")
size_t read_bytes = fread(much_data, 1, THROUGHPUT_MEASUREMENT_BYTES, f);
PERF_ADD("post")
assert(read_bytes == THROUGHPUT_MEASUREMENT_BYTES);
}
assert(fclose(f) == 0);
PERF_PRINT
}
__attribute__((__used__))
static void measure_block_driver_ump(void) {
MEASUREMENT_PREAMBLE
errval_t err;
// measurements are done inside block_driver.c for additional details
for(size_t i = 0; i < ITERATIONS; ++i) {
err = block_driver_read_object(0, 0, 0, NULL);
assert(err_is_ok(err));
}
}
__attribute__((__used__))
static void measure_pagefault_latency(void) {
MEASUREMENT_PREAMBLE
size_t test_count = 100;
uint8_t *buf = malloc(test_count * PAGE_SIZE);
for (size_t i = 0; i < test_count; ++i) {
// make the memory mapped
buf[i * PAGE_SIZE] = 1;
}
debug_printf("=============================\nDONE\n");
}
int main(int argc, char *argv[])
{
errval_t err;
barrelfish_usleep(5000000);
err = filesystem_init();
assert(err_is_ok(err));
// RUN file opening and closing performance
// measure_fopen_fclose();
// RUN file creation and deletion performance
// measure_fcreate_and_rm_single();
// RUN directory creation and deletion performance
// measure_mkdir_and_rmdir_single();
// RUN write throughput
// measure_write_throughput();
// RUN read throughput
// measure_read_throughput();
// RUN file creation performance as the file system fills up
// measure_fcreate_and_rm_many();
// RUN block driver client exercise
measure_block_driver_ump();
// RUN page fault latency measurements
// measure_pagefault_latency();
return EXIT_SUCCESS;
}