maple_tree: add benchmarking for mas_for_each

Patch series "Reduce preallocations for maple tree", v3.

Initial work on preallocations showed no regression in performance during
testing, but recently some users (both on [1] and off [android] list) have
reported that preallocating the worst-case number of nodes has caused some
slow down.  This patch set addresses the number of allocations in a few
ways.

During munmap() most munmap() operations will remove a single VMA, so
leverage the fact that the maple tree can place a single pointer at range
0 - 0 without allocating.  This is done by changing the index of the VMAs
to be indexed by the count, starting at 0.

Re-introduce the entry argument to mas_preallocate() so that a more
intelligent guess of the node count can be made.

Implement the more intelligent guess of the node count, although there is
more work to be done.

During development of v2 of this patch set, I also noticed that the number
of nodes being allocated for a rebalance was beyond what could possibly be
needed.  This is addressed in patch 0008.


This patch (of 15):

Add a way to test the speed of mas_for_each() to the testing code.

Link: https://lkml.kernel.org/r/20230724183157.3939892-1-Liam.Howlett@oracle.com
Link: https://lkml.kernel.org/r/20230724183157.3939892-2-Liam.Howlett@oracle.com
Signed-off-by: Liam R. Howlett <Liam.Howlett@oracle.com>
Cc: Peng Zhang <zhangpeng.00@bytedance.com>
Cc: Suren Baghdasaryan <surenb@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
Liam R. Howlett 2023-07-24 14:31:43 -04:00 committed by Andrew Morton
parent 90717566f8
commit 361c678be7

View File

@ -44,6 +44,7 @@ atomic_t maple_tree_tests_passed;
/* #define BENCH_WALK */
/* #define BENCH_MT_FOR_EACH */
/* #define BENCH_FORK */
/* #define BENCH_MAS_FOR_EACH */
#ifdef __KERNEL__
#define mt_set_non_kernel(x) do {} while (0)
@ -1770,6 +1771,37 @@ static noinline void __init bench_mt_for_each(struct maple_tree *mt)
}
#endif
#if defined(BENCH_MAS_FOR_EACH)
static noinline void __init bench_mas_for_each(struct maple_tree *mt)
{
int i, count = 1000000;
unsigned long max = 2500;
void *entry;
MA_STATE(mas, mt, 0, 0);
for (i = 0; i < max; i += 5) {
int gap = 4;
if (i % 30 == 0)
gap = 3;
mtree_store_range(mt, i, i + gap, xa_mk_value(i), GFP_KERNEL);
}
rcu_read_lock();
for (i = 0; i < count; i++) {
unsigned long j = 0;
mas_for_each(&mas, entry, max) {
MT_BUG_ON(mt, entry != xa_mk_value(j));
j += 5;
}
mas_set(&mas, 0);
}
rcu_read_unlock();
}
#endif
/* check_forking - simulate the kernel forking sequence with the tree. */
static noinline void __init check_forking(struct maple_tree *mt)
{
@ -3498,6 +3530,13 @@ static int __init maple_tree_seed(void)
mtree_destroy(&tree);
goto skip;
#endif
#if defined(BENCH_MAS_FOR_EACH)
#define BENCH
mt_init_flags(&tree, MT_FLAGS_ALLOC_RANGE);
bench_mas_for_each(&tree);
mtree_destroy(&tree);
goto skip;
#endif
mt_init_flags(&tree, MT_FLAGS_ALLOC_RANGE);
check_iteration(&tree);