Files
littlefs/benches/bench_mtree.toml
T
Christopher Haster 5be7bae518 Replaced tn/bn prefixes with an actual dependency system in tests/benches
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.
2023-08-04 13:33:00 -05:00

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;
'''