292 lines
6.8 KiB
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;
|
|
}
|