/** * \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 #include #include #include #include #include #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 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; }