Added bench.py and bench_runner.c for benchmarking
These are really just different flavors of test.py and test_runner.c
without support for power-loss testing, but with support for measuring
the cumulative number of bytes read, programmed, and erased.
Note that the existing define parameterization should work perfectly
fine for running benchmarks across various dimensions:
./scripts/bench.py \
runners/bench_runner \
bench_file_read \
-gnor \
-DSIZE='range(0,131072,1024)'
Also added a couple basic benchmarks as a starting point.
This commit is contained in:
@@ -0,0 +1,284 @@
|
||||
|
||||
|
||||
# deterministic prng
|
||||
code = '''
|
||||
static uint32_t xorshift32(uint32_t *state) {
|
||||
uint32_t x = *state;
|
||||
x ^= x << 13;
|
||||
x ^= x >> 17;
|
||||
x ^= x << 5;
|
||||
*state = x;
|
||||
return x;
|
||||
}
|
||||
'''
|
||||
|
||||
[cases.bench_dir_open]
|
||||
# 0 = in-order
|
||||
# 1 = reversed-order
|
||||
# 2 = random-order
|
||||
defines.ORDER = [0, 1, 2]
|
||||
defines.N = 1024
|
||||
defines.FILE_SIZE = 8
|
||||
defines.CHUNK_SIZE = 8
|
||||
code = '''
|
||||
lfs_t lfs;
|
||||
lfs_format(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
|
||||
// first create the files
|
||||
char name[256];
|
||||
uint8_t buffer[CHUNK_SIZE];
|
||||
for (lfs_size_t i = 0; i < N; i++) {
|
||||
sprintf(name, "file%08x", i);
|
||||
lfs_file_t file;
|
||||
lfs_file_open(&lfs, &file, name,
|
||||
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
|
||||
|
||||
uint32_t file_prng = i;
|
||||
for (lfs_size_t j = 0; j < FILE_SIZE; j += CHUNK_SIZE) {
|
||||
for (lfs_size_t k = 0; k < CHUNK_SIZE; k++) {
|
||||
buffer[k] = xorshift32(&file_prng);
|
||||
}
|
||||
lfs_file_write(&lfs, &file, buffer, CHUNK_SIZE) => CHUNK_SIZE;
|
||||
}
|
||||
|
||||
lfs_file_close(&lfs, &file) => 0;
|
||||
}
|
||||
|
||||
// then read the files
|
||||
BENCH_START();
|
||||
uint32_t prng = 42;
|
||||
for (lfs_size_t i = 0; i < N; i++) {
|
||||
lfs_off_t i_
|
||||
= (ORDER == 0) ? i
|
||||
: (ORDER == 1) ? (N-1-i)
|
||||
: xorshift32(&prng) % N;
|
||||
sprintf(name, "file%08x", i_);
|
||||
lfs_file_t file;
|
||||
lfs_file_open(&lfs, &file, name, LFS_O_RDONLY) => 0;
|
||||
|
||||
uint32_t file_prng = i_;
|
||||
for (lfs_size_t j = 0; j < FILE_SIZE; j += CHUNK_SIZE) {
|
||||
lfs_file_read(&lfs, &file, buffer, CHUNK_SIZE) => CHUNK_SIZE;
|
||||
for (lfs_size_t k = 0; k < CHUNK_SIZE; k++) {
|
||||
assert(buffer[k] == xorshift32(&file_prng));
|
||||
}
|
||||
}
|
||||
|
||||
lfs_file_close(&lfs, &file) => 0;
|
||||
}
|
||||
BENCH_STOP();
|
||||
|
||||
lfs_unmount(&lfs) => 0;
|
||||
'''
|
||||
|
||||
[cases.bench_dir_creat]
|
||||
# 0 = in-order
|
||||
# 1 = reversed-order
|
||||
# 2 = random-order
|
||||
defines.ORDER = [0, 1, 2]
|
||||
defines.N = 1024
|
||||
defines.FILE_SIZE = 8
|
||||
defines.CHUNK_SIZE = 8
|
||||
code = '''
|
||||
lfs_t lfs;
|
||||
lfs_format(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
|
||||
BENCH_START();
|
||||
uint32_t prng = 42;
|
||||
char name[256];
|
||||
uint8_t buffer[CHUNK_SIZE];
|
||||
for (lfs_size_t i = 0; i < N; i++) {
|
||||
lfs_off_t i_
|
||||
= (ORDER == 0) ? i
|
||||
: (ORDER == 1) ? (N-1-i)
|
||||
: xorshift32(&prng) % N;
|
||||
sprintf(name, "file%08x", i_);
|
||||
lfs_file_t file;
|
||||
lfs_file_open(&lfs, &file, name,
|
||||
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_TRUNC) => 0;
|
||||
|
||||
uint32_t file_prng = i_;
|
||||
for (lfs_size_t j = 0; j < FILE_SIZE; j += CHUNK_SIZE) {
|
||||
for (lfs_size_t k = 0; k < CHUNK_SIZE; k++) {
|
||||
buffer[k] = xorshift32(&file_prng);
|
||||
}
|
||||
lfs_file_write(&lfs, &file, buffer, CHUNK_SIZE) => CHUNK_SIZE;
|
||||
}
|
||||
|
||||
lfs_file_close(&lfs, &file) => 0;
|
||||
}
|
||||
BENCH_STOP();
|
||||
|
||||
lfs_unmount(&lfs) => 0;
|
||||
'''
|
||||
|
||||
[cases.bench_dir_remove]
|
||||
# 0 = in-order
|
||||
# 1 = reversed-order
|
||||
# 2 = random-order
|
||||
defines.ORDER = [0, 1, 2]
|
||||
defines.N = 1024
|
||||
defines.FILE_SIZE = 8
|
||||
defines.CHUNK_SIZE = 8
|
||||
code = '''
|
||||
lfs_t lfs;
|
||||
lfs_format(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
|
||||
// first create the files
|
||||
char name[256];
|
||||
uint8_t buffer[CHUNK_SIZE];
|
||||
for (lfs_size_t i = 0; i < N; i++) {
|
||||
sprintf(name, "file%08x", i);
|
||||
lfs_file_t file;
|
||||
lfs_file_open(&lfs, &file, name,
|
||||
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
|
||||
|
||||
uint32_t file_prng = i;
|
||||
for (lfs_size_t j = 0; j < FILE_SIZE; j += CHUNK_SIZE) {
|
||||
for (lfs_size_t k = 0; k < CHUNK_SIZE; k++) {
|
||||
buffer[k] = xorshift32(&file_prng);
|
||||
}
|
||||
lfs_file_write(&lfs, &file, buffer, CHUNK_SIZE) => CHUNK_SIZE;
|
||||
}
|
||||
|
||||
lfs_file_close(&lfs, &file) => 0;
|
||||
}
|
||||
|
||||
// then remove the files
|
||||
BENCH_START();
|
||||
uint32_t prng = 42;
|
||||
for (lfs_size_t i = 0; i < N; i++) {
|
||||
lfs_off_t i_
|
||||
= (ORDER == 0) ? i
|
||||
: (ORDER == 1) ? (N-1-i)
|
||||
: xorshift32(&prng) % N;
|
||||
sprintf(name, "file%08x", i_);
|
||||
int err = lfs_remove(&lfs, name);
|
||||
assert(!err || err == LFS_ERR_NOENT);
|
||||
}
|
||||
BENCH_STOP();
|
||||
|
||||
lfs_unmount(&lfs) => 0;
|
||||
'''
|
||||
|
||||
[cases.bench_dir_read]
|
||||
defines.N = 1024
|
||||
defines.FILE_SIZE = 8
|
||||
defines.CHUNK_SIZE = 8
|
||||
code = '''
|
||||
lfs_t lfs;
|
||||
lfs_format(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
|
||||
// first create the files
|
||||
char name[256];
|
||||
uint8_t buffer[CHUNK_SIZE];
|
||||
for (lfs_size_t i = 0; i < N; i++) {
|
||||
sprintf(name, "file%08x", i);
|
||||
lfs_file_t file;
|
||||
lfs_file_open(&lfs, &file, name,
|
||||
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
|
||||
|
||||
uint32_t file_prng = i;
|
||||
for (lfs_size_t j = 0; j < FILE_SIZE; j += CHUNK_SIZE) {
|
||||
for (lfs_size_t k = 0; k < CHUNK_SIZE; k++) {
|
||||
buffer[k] = xorshift32(&file_prng);
|
||||
}
|
||||
lfs_file_write(&lfs, &file, buffer, CHUNK_SIZE) => CHUNK_SIZE;
|
||||
}
|
||||
|
||||
lfs_file_close(&lfs, &file) => 0;
|
||||
}
|
||||
|
||||
// then read the directory
|
||||
BENCH_START();
|
||||
lfs_dir_t dir;
|
||||
lfs_dir_open(&lfs, &dir, "/") => 0;
|
||||
struct lfs_info info;
|
||||
lfs_dir_read(&lfs, &dir, &info) => 1;
|
||||
assert(info.type == LFS_TYPE_DIR);
|
||||
assert(strcmp(info.name, ".") == 0);
|
||||
lfs_dir_read(&lfs, &dir, &info) => 1;
|
||||
assert(info.type == LFS_TYPE_DIR);
|
||||
assert(strcmp(info.name, "..") == 0);
|
||||
for (int i = 0; i < N; i++) {
|
||||
sprintf(name, "file%08x", i);
|
||||
lfs_dir_read(&lfs, &dir, &info) => 1;
|
||||
assert(info.type == LFS_TYPE_REG);
|
||||
assert(strcmp(info.name, name) == 0);
|
||||
}
|
||||
lfs_dir_read(&lfs, &dir, &info) => 0;
|
||||
lfs_dir_close(&lfs, &dir) => 0;
|
||||
BENCH_STOP();
|
||||
|
||||
lfs_unmount(&lfs) => 0;
|
||||
'''
|
||||
|
||||
[cases.bench_dir_mkdir]
|
||||
# 0 = in-order
|
||||
# 1 = reversed-order
|
||||
# 2 = random-order
|
||||
defines.ORDER = [0, 1, 2]
|
||||
defines.N = 8
|
||||
code = '''
|
||||
lfs_t lfs;
|
||||
lfs_format(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
|
||||
BENCH_START();
|
||||
uint32_t prng = 42;
|
||||
char name[256];
|
||||
for (lfs_size_t i = 0; i < N; i++) {
|
||||
lfs_off_t i_
|
||||
= (ORDER == 0) ? i
|
||||
: (ORDER == 1) ? (N-1-i)
|
||||
: xorshift32(&prng) % N;
|
||||
printf("hm %d\n", i);
|
||||
sprintf(name, "dir%08x", i_);
|
||||
int err = lfs_mkdir(&lfs, name);
|
||||
assert(!err || err == LFS_ERR_EXIST);
|
||||
}
|
||||
BENCH_STOP();
|
||||
|
||||
lfs_unmount(&lfs) => 0;
|
||||
'''
|
||||
|
||||
[cases.bench_dir_rmdir]
|
||||
# 0 = in-order
|
||||
# 1 = reversed-order
|
||||
# 2 = random-order
|
||||
defines.ORDER = [0, 1, 2]
|
||||
defines.N = 8
|
||||
code = '''
|
||||
lfs_t lfs;
|
||||
lfs_format(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
|
||||
// first create the dirs
|
||||
char name[256];
|
||||
for (lfs_size_t i = 0; i < N; i++) {
|
||||
sprintf(name, "dir%08x", i);
|
||||
lfs_mkdir(&lfs, name) => 0;
|
||||
}
|
||||
|
||||
// then remove the dirs
|
||||
BENCH_START();
|
||||
uint32_t prng = 42;
|
||||
for (lfs_size_t i = 0; i < N; i++) {
|
||||
lfs_off_t i_
|
||||
= (ORDER == 0) ? i
|
||||
: (ORDER == 1) ? (N-1-i)
|
||||
: xorshift32(&prng) % N;
|
||||
sprintf(name, "dir%08x", i_);
|
||||
int err = lfs_remove(&lfs, name);
|
||||
assert(!err || err == LFS_ERR_NOENT);
|
||||
}
|
||||
BENCH_STOP();
|
||||
|
||||
lfs_unmount(&lfs) => 0;
|
||||
'''
|
||||
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
|
||||
|
||||
# deterministic prng
|
||||
code = '''
|
||||
static uint32_t xorshift32(uint32_t *state) {
|
||||
uint32_t x = *state;
|
||||
x ^= x << 13;
|
||||
x ^= x >> 17;
|
||||
x ^= x << 5;
|
||||
*state = x;
|
||||
return x;
|
||||
}
|
||||
'''
|
||||
|
||||
[cases.bench_file_read]
|
||||
# 0 = in-order
|
||||
# 1 = reversed-order
|
||||
# 2 = random-order
|
||||
defines.ORDER = [0, 1, 2]
|
||||
defines.SIZE = '128*1024'
|
||||
defines.CHUNK_SIZE = 64
|
||||
code = '''
|
||||
lfs_t lfs;
|
||||
lfs_format(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
lfs_size_t chunks = (SIZE+CHUNK_SIZE-1)/CHUNK_SIZE;
|
||||
|
||||
// first write the file
|
||||
lfs_file_t file;
|
||||
uint8_t buffer[CHUNK_SIZE];
|
||||
lfs_file_open(&lfs, &file, "file",
|
||||
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
|
||||
for (lfs_size_t i = 0; i < chunks; i++) {
|
||||
uint32_t chunk_prng = i;
|
||||
for (lfs_size_t j = 0; j < CHUNK_SIZE; j++) {
|
||||
buffer[j] = xorshift32(&chunk_prng);
|
||||
}
|
||||
|
||||
lfs_file_write(&lfs, &file, buffer, CHUNK_SIZE) => CHUNK_SIZE;
|
||||
}
|
||||
lfs_file_write(&lfs, &file, buffer, CHUNK_SIZE) => CHUNK_SIZE;
|
||||
lfs_file_close(&lfs, &file) => 0;
|
||||
|
||||
// then read the file
|
||||
BENCH_START();
|
||||
lfs_file_open(&lfs, &file, "file", LFS_O_RDONLY) => 0;
|
||||
|
||||
uint32_t prng = 42;
|
||||
for (lfs_size_t i = 0; i < chunks; i++) {
|
||||
lfs_off_t i_
|
||||
= (ORDER == 0) ? i
|
||||
: (ORDER == 1) ? (chunks-1-i)
|
||||
: xorshift32(&prng) % chunks;
|
||||
lfs_file_seek(&lfs, &file, i_*CHUNK_SIZE, LFS_SEEK_SET)
|
||||
=> i_*CHUNK_SIZE;
|
||||
lfs_file_read(&lfs, &file, buffer, CHUNK_SIZE) => CHUNK_SIZE;
|
||||
|
||||
uint32_t chunk_prng = i_;
|
||||
for (lfs_size_t j = 0; j < CHUNK_SIZE; j++) {
|
||||
assert(buffer[j] == xorshift32(&chunk_prng));
|
||||
}
|
||||
}
|
||||
|
||||
lfs_file_close(&lfs, &file) => 0;
|
||||
BENCH_STOP();
|
||||
|
||||
lfs_unmount(&lfs) => 0;
|
||||
'''
|
||||
|
||||
[cases.bench_file_write]
|
||||
# 0 = in-order
|
||||
# 1 = reversed-order
|
||||
# 2 = random-order
|
||||
defines.ORDER = [0, 1, 2]
|
||||
defines.SIZE = '128*1024'
|
||||
defines.CHUNK_SIZE = 64
|
||||
code = '''
|
||||
lfs_t lfs;
|
||||
lfs_format(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
lfs_size_t chunks = (SIZE+CHUNK_SIZE-1)/CHUNK_SIZE;
|
||||
|
||||
BENCH_START();
|
||||
lfs_file_t file;
|
||||
lfs_file_open(&lfs, &file, "file",
|
||||
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
|
||||
|
||||
uint8_t buffer[CHUNK_SIZE];
|
||||
uint32_t prng = 42;
|
||||
for (lfs_size_t i = 0; i < chunks; i++) {
|
||||
lfs_off_t i_
|
||||
= (ORDER == 0) ? i
|
||||
: (ORDER == 1) ? (chunks-1-i)
|
||||
: xorshift32(&prng) % chunks;
|
||||
uint32_t chunk_prng = i_;
|
||||
for (lfs_size_t j = 0; j < CHUNK_SIZE; j++) {
|
||||
buffer[j] = xorshift32(&chunk_prng);
|
||||
}
|
||||
|
||||
lfs_file_seek(&lfs, &file, i_*CHUNK_SIZE, LFS_SEEK_SET)
|
||||
=> i_*CHUNK_SIZE;
|
||||
lfs_file_write(&lfs, &file, buffer, CHUNK_SIZE) => CHUNK_SIZE;
|
||||
}
|
||||
|
||||
lfs_file_close(&lfs, &file) => 0;
|
||||
BENCH_STOP();
|
||||
|
||||
lfs_unmount(&lfs) => 0;
|
||||
'''
|
||||
@@ -0,0 +1,56 @@
|
||||
[cases.bench_superblocks_found]
|
||||
# support benchmarking with files
|
||||
defines.N = [0, 1024]
|
||||
defines.FILE_SIZE = 8
|
||||
defines.CHUNK_SIZE = 8
|
||||
code = '''
|
||||
lfs_t lfs;
|
||||
lfs_format(&lfs, cfg) => 0;
|
||||
|
||||
// create files?
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
char name[256];
|
||||
uint8_t buffer[CHUNK_SIZE];
|
||||
for (lfs_size_t i = 0; i < N; i++) {
|
||||
sprintf(name, "file%08x", i);
|
||||
lfs_file_t file;
|
||||
lfs_file_open(&lfs, &file, name,
|
||||
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
|
||||
|
||||
for (lfs_size_t j = 0; j < FILE_SIZE; j += CHUNK_SIZE) {
|
||||
for (lfs_size_t k = 0; k < CHUNK_SIZE; k++) {
|
||||
buffer[k] = i+j+k;
|
||||
}
|
||||
lfs_file_write(&lfs, &file, buffer, CHUNK_SIZE) => CHUNK_SIZE;
|
||||
}
|
||||
|
||||
lfs_file_close(&lfs, &file) => 0;
|
||||
}
|
||||
lfs_unmount(&lfs) => 0;
|
||||
|
||||
BENCH_START();
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
BENCH_STOP();
|
||||
|
||||
lfs_unmount(&lfs) => 0;
|
||||
'''
|
||||
|
||||
[cases.bench_superblocks_missing]
|
||||
code = '''
|
||||
lfs_t lfs;
|
||||
|
||||
BENCH_START();
|
||||
int err = lfs_mount(&lfs, cfg);
|
||||
assert(err != 0);
|
||||
BENCH_STOP();
|
||||
'''
|
||||
|
||||
[cases.bench_superblocks_format]
|
||||
code = '''
|
||||
lfs_t lfs;
|
||||
|
||||
BENCH_START();
|
||||
lfs_format(&lfs, cfg) => 0;
|
||||
BENCH_STOP();
|
||||
'''
|
||||
|
||||
Reference in New Issue
Block a user