Files
littlefs/benches/bench_mtree.toml
T
Christopher Haster f7d4497b80 Added some simple mtree benchmarks
It's interesting to note the different performance characteristics of
purely CoW btrees vs our mutable mtree.

The main downside of our mtree is the need to fetch leaf mdirs. This
fetch is expensive, and can be avoided in CoW btrees by storing the
trunk in each branch's parent.

On the other hand, btrees need to propagate all changes upwards to the
root.

An interesting takeaway is that a sort of mdir-trunk cache may be a very
interesting optimization for relatively little RAM cost. This may be
something to explore in the future.
2023-05-30 18:04:48 -05:00

136 lines
3.8 KiB
TOML

# 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;
// 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, MKINLINED, +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;
// 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, MKINLINED, +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, MKINLINED, +1, "C", 1))) => 0;
BENCH_STOP();
lfsr_unmount(&lfs) => 0;
'''