5be7bae518
The previous system of relying on test name prefixes for ordering was simple, but organizing tests by dependencies and topologically sorting during compilation is 1. more flexible and 2. simplifies test names, which get typed a lot. Note these are not "hard" dependencies, each test suite should work fine in isolation. These "after" dependencies just hint an ordering when all tests are ran. As such, it's worth noting the tests should NOT error of a dependency is missing. This unfortunately makes it a bit hard to catch typos, but allows faster compilation of a subset of tests. --- To make this work the way tests are linked has changed from using custom linker section (fun linker magic!) to a weakly linked array appended to every source file (also fun linker magic!). At least with this method test.py has strict control over the test ordering, and doesn't depend on 1. the order in which the linker merges sections, and 2. the order tests are passed to test.py. I didn't realize the previous system was so fragile.
207 lines
5.9 KiB
TOML
207 lines
5.9 KiB
TOML
# Bench our high-level metadata tree in the core of littlefs
|
|
after = ['bench_rbyd', 'bench_btree']
|
|
|
|
# maximize lookahead buffer, we don't actually gc so we only get one pass
|
|
# of the disk for these tests
|
|
defines.LOOKAHEAD_SIZE = 'BLOCK_COUNT / 8'
|
|
|
|
[cases.bench_mtree_lookup]
|
|
defines.N = [8, 16, 32, 64, 128, 256, 1024]
|
|
# 0 = in-order
|
|
# 1 = reversed-order
|
|
# 2 = random-order
|
|
defines.ORDER = [0, 1, 2]
|
|
defines.SEED = 42
|
|
in = 'lfs.c'
|
|
code = '''
|
|
uint32_t prng = SEED;
|
|
const char *alphas = "abcdefghijklmnopqrstuvwxyz";
|
|
|
|
lfs_t lfs;
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
lfs_alloc_ack(&lfs);
|
|
|
|
// create an mtree with N entries
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
// choose an mid
|
|
lfs_ssize_t mid
|
|
= lfsr_mtree_weight(&lfs) == 0 ? -1
|
|
: (ORDER == 0) ? (lfs_ssize_t)(lfsr_mtree_weight(&lfs)-1)
|
|
: (ORDER == 1) ? 0
|
|
: (lfs_ssize_t)(BENCH_PRNG(&prng) % lfsr_mtree_weight(&lfs));
|
|
// fetch mdir
|
|
lfsr_mdir_t mdir;
|
|
lfsr_mtree_lookup(&lfs, mid, &mdir) => 0;
|
|
|
|
// choose rid
|
|
lfs_ssize_t rid
|
|
= (ORDER == 0) ? lfsr_mdir_weight(&mdir)
|
|
: (ORDER == 1) ? 0
|
|
: BENCH_PRNG(&prng) % (lfsr_mdir_weight(&mdir)+1);
|
|
|
|
// create an entry
|
|
lfsr_mdir_commit(&lfs, &mdir, &rid, LFSR_ATTRS(
|
|
LFSR_ATTR(rid, INLINED, +1, &alphas[i % 26], 1))) => 0;
|
|
}
|
|
|
|
// bench lookup
|
|
BENCH_START();
|
|
// choose an mid
|
|
lfs_ssize_t mid
|
|
= lfsr_mtree_weight(&lfs) == 0 ? -1
|
|
: (lfs_ssize_t)(BENCH_PRNG(&prng) % lfsr_mtree_weight(&lfs));
|
|
// fetch mdir
|
|
lfsr_mdir_t mdir;
|
|
lfsr_mtree_lookup(&lfs, mid, &mdir) => 0;
|
|
|
|
// choose rid
|
|
lfs_ssize_t rid = BENCH_PRNG(&prng) % lfsr_mdir_weight(&mdir);
|
|
|
|
// lookup
|
|
uint8_t buffer[4];
|
|
lfsr_mdir_get(&lfs, &mdir, rid, LFSR_TAG_INLINED, buffer, 4) => 1;
|
|
BENCH_STOP();
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
[cases.bench_mtree_commit]
|
|
defines.N = [8, 16, 32, 64, 128, 256, 1024]
|
|
# 0 = in-order
|
|
# 1 = reversed-order
|
|
# 2 = random-order
|
|
defines.ORDER = [0, 1, 2]
|
|
defines.SEED = 42
|
|
defines.AMORTIZED = false
|
|
in = 'lfs.c'
|
|
code = '''
|
|
uint32_t prng = SEED;
|
|
const char *alphas = "abcdefghijklmnopqrstuvwxyz";
|
|
|
|
lfs_t lfs;
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
lfs_alloc_ack(&lfs);
|
|
|
|
// create an mtree with N entries
|
|
if (AMORTIZED) {
|
|
BENCH_START();
|
|
}
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
// choose an mid
|
|
lfs_ssize_t mid
|
|
= lfsr_mtree_weight(&lfs) == 0 ? -1
|
|
: (ORDER == 0) ? (lfs_ssize_t)(lfsr_mtree_weight(&lfs)-1)
|
|
: (ORDER == 1) ? 0
|
|
: (lfs_ssize_t)(BENCH_PRNG(&prng) % lfsr_mtree_weight(&lfs));
|
|
// fetch mdir
|
|
lfsr_mdir_t mdir;
|
|
lfsr_mtree_lookup(&lfs, mid, &mdir) => 0;
|
|
|
|
// choose rid
|
|
lfs_ssize_t rid
|
|
= (ORDER == 0) ? lfsr_mdir_weight(&mdir)
|
|
: (ORDER == 1) ? 0
|
|
: BENCH_PRNG(&prng) % (lfsr_mdir_weight(&mdir)+1);
|
|
|
|
// create an entry
|
|
lfsr_mdir_commit(&lfs, &mdir, &rid, LFSR_ATTRS(
|
|
LFSR_ATTR(rid, INLINED, +1, &alphas[i % 26], 1))) => 0;
|
|
}
|
|
|
|
// bench commit
|
|
if (!AMORTIZED) {
|
|
BENCH_START();
|
|
}
|
|
// choose an mid
|
|
lfs_ssize_t mid
|
|
= lfsr_mtree_weight(&lfs) == 0 ? -1
|
|
: (ORDER == 0) ? (lfs_ssize_t)(lfsr_mtree_weight(&lfs)-1)
|
|
: (ORDER == 1) ? 0
|
|
: (lfs_ssize_t)(BENCH_PRNG(&prng) % lfsr_mtree_weight(&lfs));
|
|
// fetch mdir
|
|
lfsr_mdir_t mdir;
|
|
lfsr_mtree_lookup(&lfs, mid, &mdir) => 0;
|
|
|
|
// choose rid
|
|
lfs_ssize_t rid
|
|
= (ORDER == 0) ? lfsr_mdir_weight(&mdir)
|
|
: (ORDER == 1) ? 0
|
|
: BENCH_PRNG(&prng) % (lfsr_mdir_weight(&mdir)+1);
|
|
|
|
// create an entry
|
|
lfsr_mdir_commit(&lfs, &mdir, &rid, LFSR_ATTRS(
|
|
LFSR_ATTR(rid, INLINED, +1, "C", 1))) => 0;
|
|
BENCH_STOP();
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|
|
|
|
[cases.bench_mtree_traversal]
|
|
defines.N = [8, 16, 32, 64, 128, 256, 1024]
|
|
# 0 = in-order
|
|
# 1 = reversed-order
|
|
# 2 = random-order
|
|
defines.ORDER = [0, 1, 2]
|
|
defines.SEED = 42
|
|
defines.VALIDATE = [false, true]
|
|
in = 'lfs.c'
|
|
code = '''
|
|
uint32_t prng = SEED;
|
|
const char *alphas = "abcdefghijklmnopqrstuvwxyz";
|
|
|
|
lfs_t lfs;
|
|
lfsr_format(&lfs, cfg) => 0;
|
|
lfsr_mount(&lfs, cfg) => 0;
|
|
lfs_alloc_ack(&lfs);
|
|
|
|
// create an mtree with N entries
|
|
for (lfs_size_t i = 0; i < N; i++) {
|
|
// choose an mid
|
|
lfs_ssize_t mid
|
|
= lfsr_mtree_weight(&lfs) == 0 ? -1
|
|
: (ORDER == 0) ? (lfs_ssize_t)(lfsr_mtree_weight(&lfs)-1)
|
|
: (ORDER == 1) ? 0
|
|
: (lfs_ssize_t)(BENCH_PRNG(&prng) % lfsr_mtree_weight(&lfs));
|
|
// fetch mdir
|
|
lfsr_mdir_t mdir;
|
|
lfsr_mtree_lookup(&lfs, mid, &mdir) => 0;
|
|
|
|
// choose rid
|
|
lfs_ssize_t rid
|
|
= (ORDER == 0) ? lfsr_mdir_weight(&mdir)
|
|
: (ORDER == 1) ? 0
|
|
: BENCH_PRNG(&prng) % (lfsr_mdir_weight(&mdir)+1);
|
|
|
|
// create an entry
|
|
lfsr_mdir_commit(&lfs, &mdir, &rid, LFSR_ATTRS(
|
|
LFSR_ATTR(rid, INLINED, +1, &alphas[i % 26], 1))) => 0;
|
|
}
|
|
|
|
// traverse the mtree
|
|
BENCH_START();
|
|
lfsr_mtree_traversal_t traversal = LFSR_MTREE_TRAVERSAL_INIT(
|
|
VALIDATE ? LFSR_MTREE_TRAVERSAL_VALIDATE : 0);
|
|
|
|
for (lfs_block_t i = 0;; i++) {
|
|
// a bit hacky, but this catches infinite loops
|
|
assert(i < 2*(1+N));
|
|
|
|
lfs_size_t mid_;
|
|
lfsr_tag_t tag_;
|
|
lfsr_data_t data_;
|
|
int err = lfsr_mtree_traversal_next(&lfs, &traversal,
|
|
&mid_, &tag_, &data_);
|
|
assert(!err || err == LFS_ERR_NOENT);
|
|
if (err == LFS_ERR_NOENT) {
|
|
break;
|
|
}
|
|
|
|
assert(tag_ == LFSR_TAG_BTREE || tag_ == LFSR_TAG_MDIR);
|
|
}
|
|
BENCH_STOP();
|
|
|
|
lfsr_unmount(&lfs) => 0;
|
|
'''
|