* [PATCH 1/2] maple tree: Clean up mtree_range_walk() @ 2025-06-26 17:19 Dev Jain 2025-06-26 17:19 ` [PATCH 2/2] maple tree: Add and fix some comments Dev Jain 2025-06-26 19:58 ` [PATCH 1/2] maple tree: Clean up mtree_range_walk() Liam R. Howlett 0 siblings, 2 replies; 10+ messages in thread From: Dev Jain @ 2025-06-26 17:19 UTC (permalink / raw) To: akpm, Liam.Howlett Cc: richard.weiyang, maple-tree, linux-mm, linux-kernel, Dev Jain The special casing for offset == 0 is being done because min will stay mas->min in this case. So refactor the code to use the while loop for setting the max and getting the corresponding offset, and only set the min for offset > 0. Signed-off-by: Dev Jain <dev.jain@arm.com> --- lib/maple_tree.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/lib/maple_tree.c b/lib/maple_tree.c index 0e85e92c5375..6c89e6790fb5 100644 --- a/lib/maple_tree.c +++ b/lib/maple_tree.c @@ -2770,13 +2770,8 @@ static inline void *mtree_range_walk(struct ma_state *mas) end = ma_data_end(node, type, pivots, max); prev_min = min; prev_max = max; - if (pivots[0] >= mas->index) { - offset = 0; - max = pivots[0]; - goto next; - } - offset = 1; + offset = 0; while (offset < end) { if (pivots[offset] >= mas->index) { max = pivots[offset]; @@ -2784,9 +2779,9 @@ static inline void *mtree_range_walk(struct ma_state *mas) } offset++; } + if (likely(offset)) + min = pivots[offset - 1] + 1; - min = pivots[offset - 1] + 1; -next: slots = ma_slots(node, type); next = mt_slot(mas->tree, slots, offset); if (unlikely(ma_dead_node(node))) -- 2.30.2 ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 2/2] maple tree: Add and fix some comments 2025-06-26 17:19 [PATCH 1/2] maple tree: Clean up mtree_range_walk() Dev Jain @ 2025-06-26 17:19 ` Dev Jain 2025-06-26 20:04 ` Liam R. Howlett 2025-06-26 19:58 ` [PATCH 1/2] maple tree: Clean up mtree_range_walk() Liam R. Howlett 1 sibling, 1 reply; 10+ messages in thread From: Dev Jain @ 2025-06-26 17:19 UTC (permalink / raw) To: akpm, Liam.Howlett Cc: richard.weiyang, maple-tree, linux-mm, linux-kernel, Dev Jain Add comments explaining the fields for maple_metadata, since "end" is ambiguous and "gap" can be confused as the largest gap, whereas it is actually the offset of the largest gap. MAPLE_ROOT_NODE is used for mt_mk_root() and mt_safe_root(), indicating that it is used to mark the node as root. So fix the comment. Add comment for mas_ascend() to explain, whose min and max we are trying to find. Explain that, for example, if we are already on offset zero, then the parent min is mas->min, otherwise we need to walk up to find the implied pivot min. Signed-off-by: Dev Jain <dev.jain@arm.com> --- include/linux/maple_tree.h | 4 ++-- lib/maple_tree.c | 9 +++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/include/linux/maple_tree.h b/include/linux/maple_tree.h index 9ef129038224..bafe143b1f78 100644 --- a/include/linux/maple_tree.h +++ b/include/linux/maple_tree.h @@ -75,8 +75,8 @@ * searching for gaps or any other code that needs to find the end of the data. */ struct maple_metadata { - unsigned char end; - unsigned char gap; + unsigned char end; /* end of data */ + unsigned char gap; /* offset of largest gap */ }; /* diff --git a/lib/maple_tree.c b/lib/maple_tree.c index 6c89e6790fb5..e4735ccd06f2 100644 --- a/lib/maple_tree.c +++ b/lib/maple_tree.c @@ -338,7 +338,7 @@ static inline void mte_set_node_dead(struct maple_enode *mn) smp_wmb(); /* Needed for RCU */ } -/* Bit 1 indicates the root is a node */ +/* Bit 1 indicates the node is the root */ #define MAPLE_ROOT_NODE 0x02 /* maple_type stored bit 3-6 */ #define MAPLE_ENODE_TYPE_SHIFT 0x03 @@ -1053,7 +1053,7 @@ static inline void mte_set_gap(const struct maple_enode *mn, * mas_ascend() - Walk up a level of the tree. * @mas: The maple state * - * Sets the @mas->max and @mas->min to the correct values when walking up. This + * Sets the @mas->max and @mas->min for the parent node of mas->node. This * may cause several levels of walking up to find the correct min and max. * May find a dead node which will cause a premature return. * Return: 1 on dead node, 0 otherwise @@ -1098,6 +1098,11 @@ static int mas_ascend(struct ma_state *mas) min = 0; max = ULONG_MAX; + + /* + * !mas->offset => parent node min == mas->min. mas->offset => need + * to walk up to find the implied pivot min. + */ if (!mas->offset) { min = mas->min; set_min = true; -- 2.30.2 ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 2/2] maple tree: Add and fix some comments 2025-06-26 17:19 ` [PATCH 2/2] maple tree: Add and fix some comments Dev Jain @ 2025-06-26 20:04 ` Liam R. Howlett 2025-06-28 11:56 ` Dev Jain 0 siblings, 1 reply; 10+ messages in thread From: Liam R. Howlett @ 2025-06-26 20:04 UTC (permalink / raw) To: Dev Jain; +Cc: akpm, richard.weiyang, maple-tree, linux-mm, linux-kernel * Dev Jain <dev.jain@arm.com> [250626 13:19]: > Add comments explaining the fields for maple_metadata, since "end" is > ambiguous and "gap" can be confused as the largest gap, whereas it > is actually the offset of the largest gap. > > MAPLE_ROOT_NODE is used for mt_mk_root() and mt_safe_root(), indicating > that it is used to mark the node as root. So fix the comment. That's not quite the entire story here. The first pointer in the tree may not be a node at all, and may be an entry. So having that bit set tells us the root of the tree is a node, so the comment is correct but maybe you have a better way of expressing this information? > > Add comment for mas_ascend() to explain, whose min and max we are > trying to find. Explain that, for example, if we are already on offset > zero, then the parent min is mas->min, otherwise we need to walk up > to find the implied pivot min. > > Signed-off-by: Dev Jain <dev.jain@arm.com> > --- > include/linux/maple_tree.h | 4 ++-- > lib/maple_tree.c | 9 +++++++-- > 2 files changed, 9 insertions(+), 4 deletions(-) > > diff --git a/include/linux/maple_tree.h b/include/linux/maple_tree.h > index 9ef129038224..bafe143b1f78 100644 > --- a/include/linux/maple_tree.h > +++ b/include/linux/maple_tree.h > @@ -75,8 +75,8 @@ > * searching for gaps or any other code that needs to find the end of the data. > */ > struct maple_metadata { > - unsigned char end; > - unsigned char gap; > + unsigned char end; /* end of data */ > + unsigned char gap; /* offset of largest gap */ Thanks. > }; > > /* > diff --git a/lib/maple_tree.c b/lib/maple_tree.c > index 6c89e6790fb5..e4735ccd06f2 100644 > --- a/lib/maple_tree.c > +++ b/lib/maple_tree.c > @@ -338,7 +338,7 @@ static inline void mte_set_node_dead(struct maple_enode *mn) > smp_wmb(); /* Needed for RCU */ > } > > -/* Bit 1 indicates the root is a node */ > +/* Bit 1 indicates the node is the root */ > #define MAPLE_ROOT_NODE 0x02 > /* maple_type stored bit 3-6 */ > #define MAPLE_ENODE_TYPE_SHIFT 0x03 > @@ -1053,7 +1053,7 @@ static inline void mte_set_gap(const struct maple_enode *mn, > * mas_ascend() - Walk up a level of the tree. > * @mas: The maple state > * > - * Sets the @mas->max and @mas->min to the correct values when walking up. This > + * Sets the @mas->max and @mas->min for the parent node of mas->node. This > * may cause several levels of walking up to find the correct min and max. > * May find a dead node which will cause a premature return. > * Return: 1 on dead node, 0 otherwise > @@ -1098,6 +1098,11 @@ static int mas_ascend(struct ma_state *mas) > > min = 0; > max = ULONG_MAX; > + > + /* > + * !mas->offset => parent node min == mas->min. mas->offset => need > + * to walk up to find the implied pivot min. The => arrows here are a bit hard to parse, especially mixed with ==. Maybe use more words? > + */ > if (!mas->offset) { > min = mas->min; > set_min = true; > -- > 2.30.2 > ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 2/2] maple tree: Add and fix some comments 2025-06-26 20:04 ` Liam R. Howlett @ 2025-06-28 11:56 ` Dev Jain 2025-06-29 23:16 ` Wei Yang 2025-07-03 5:54 ` Liam R. Howlett 0 siblings, 2 replies; 10+ messages in thread From: Dev Jain @ 2025-06-28 11:56 UTC (permalink / raw) To: Liam R. Howlett, akpm, richard.weiyang, maple-tree, linux-mm, linux-kernel On 27/06/25 1:34 am, Liam R. Howlett wrote: > * Dev Jain <dev.jain@arm.com> [250626 13:19]: >> Add comments explaining the fields for maple_metadata, since "end" is >> ambiguous and "gap" can be confused as the largest gap, whereas it >> is actually the offset of the largest gap. >> >> MAPLE_ROOT_NODE is used for mt_mk_root() and mt_safe_root(), indicating >> that it is used to mark the node as root. So fix the comment. > That's not quite the entire story here. > > The first pointer in the tree may not be a node at all, and may be an > entry. So having that bit set tells us the root of the tree is a node, > so the comment is correct but maybe you have a better way of expressing > this information? Hmm. Can you please correct me on my understanding - when we have an empty tree, then we insert a root and can store a value there. Now when we store the second entry, we allocate a node and make the root a node, the root points to that node, and we store the values at offsets 0 and 1. I am reading more to answer my own question. > > >> Add comment for mas_ascend() to explain, whose min and max we are >> trying to find. Explain that, for example, if we are already on offset >> zero, then the parent min is mas->min, otherwise we need to walk up >> to find the implied pivot min. >> >> Signed-off-by: Dev Jain <dev.jain@arm.com> >> --- >> include/linux/maple_tree.h | 4 ++-- >> lib/maple_tree.c | 9 +++++++-- >> 2 files changed, 9 insertions(+), 4 deletions(-) >> >> diff --git a/include/linux/maple_tree.h b/include/linux/maple_tree.h >> index 9ef129038224..bafe143b1f78 100644 >> --- a/include/linux/maple_tree.h >> +++ b/include/linux/maple_tree.h >> @@ -75,8 +75,8 @@ >> * searching for gaps or any other code that needs to find the end of the data. >> */ >> struct maple_metadata { >> - unsigned char end; >> - unsigned char gap; >> + unsigned char end; /* end of data */ >> + unsigned char gap; /* offset of largest gap */ > Thanks. > >> }; >> >> /* >> diff --git a/lib/maple_tree.c b/lib/maple_tree.c >> index 6c89e6790fb5..e4735ccd06f2 100644 >> --- a/lib/maple_tree.c >> +++ b/lib/maple_tree.c >> @@ -338,7 +338,7 @@ static inline void mte_set_node_dead(struct maple_enode *mn) >> smp_wmb(); /* Needed for RCU */ >> } >> >> -/* Bit 1 indicates the root is a node */ >> +/* Bit 1 indicates the node is the root */ >> #define MAPLE_ROOT_NODE 0x02 >> /* maple_type stored bit 3-6 */ >> #define MAPLE_ENODE_TYPE_SHIFT 0x03 >> @@ -1053,7 +1053,7 @@ static inline void mte_set_gap(const struct maple_enode *mn, >> * mas_ascend() - Walk up a level of the tree. >> * @mas: The maple state >> * >> - * Sets the @mas->max and @mas->min to the correct values when walking up. This >> + * Sets the @mas->max and @mas->min for the parent node of mas->node. This >> * may cause several levels of walking up to find the correct min and max. >> * May find a dead node which will cause a premature return. >> * Return: 1 on dead node, 0 otherwise >> @@ -1098,6 +1098,11 @@ static int mas_ascend(struct ma_state *mas) >> >> min = 0; >> max = ULONG_MAX; >> + >> + /* >> + * !mas->offset => parent node min == mas->min. mas->offset => need >> + * to walk up to find the implied pivot min. > The => arrows here are a bit hard to parse, especially mixed with ==. > Maybe use more words? Okay. > >> + */ >> if (!mas->offset) { >> min = mas->min; >> set_min = true; >> -- >> 2.30.2 >> ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 2/2] maple tree: Add and fix some comments 2025-06-28 11:56 ` Dev Jain @ 2025-06-29 23:16 ` Wei Yang 2025-07-03 5:54 ` Liam R. Howlett 1 sibling, 0 replies; 10+ messages in thread From: Wei Yang @ 2025-06-29 23:16 UTC (permalink / raw) To: Dev Jain Cc: Liam R. Howlett, akpm, richard.weiyang, maple-tree, linux-mm, linux-kernel On Sat, Jun 28, 2025 at 05:26:18PM +0530, Dev Jain wrote: > >On 27/06/25 1:34 am, Liam R. Howlett wrote: >> * Dev Jain <dev.jain@arm.com> [250626 13:19]: >> > Add comments explaining the fields for maple_metadata, since "end" is >> > ambiguous and "gap" can be confused as the largest gap, whereas it >> > is actually the offset of the largest gap. >> > >> > MAPLE_ROOT_NODE is used for mt_mk_root() and mt_safe_root(), indicating >> > that it is used to mark the node as root. So fix the comment. >> That's not quite the entire story here. >> >> The first pointer in the tree may not be a node at all, and may be an >> entry. So having that bit set tells us the root of the tree is a node, >> so the comment is correct but maybe you have a better way of expressing >> this information? > >Hmm. Can you please correct me on my understanding - when we have an >empty tree, then we insert a root and can store a value there. Now when >we store the second entry, we allocate a node and make the root a node, >the root points to that node, and we store the values at offsets 0 and 1. > Per my understanding, generally it is correct. You may take a look at tools/testing/radix-tree/maple.c and use mt_dump() to see how the tree changes. >I am reading more to answer my own question. > -- Wei Yang Help you, Help me ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 2/2] maple tree: Add and fix some comments 2025-06-28 11:56 ` Dev Jain 2025-06-29 23:16 ` Wei Yang @ 2025-07-03 5:54 ` Liam R. Howlett 2025-07-03 6:14 ` Dev Jain 1 sibling, 1 reply; 10+ messages in thread From: Liam R. Howlett @ 2025-07-03 5:54 UTC (permalink / raw) To: Dev Jain; +Cc: akpm, richard.weiyang, maple-tree, linux-mm, linux-kernel * Dev Jain <dev.jain@arm.com> [250628 07:57]: > > On 27/06/25 1:34 am, Liam R. Howlett wrote: > > * Dev Jain <dev.jain@arm.com> [250626 13:19]: > > > Add comments explaining the fields for maple_metadata, since "end" is > > > ambiguous and "gap" can be confused as the largest gap, whereas it > > > is actually the offset of the largest gap. > > > > > > MAPLE_ROOT_NODE is used for mt_mk_root() and mt_safe_root(), indicating > > > that it is used to mark the node as root. So fix the comment. > > That's not quite the entire story here. > > > > The first pointer in the tree may not be a node at all, and may be an > > entry. So having that bit set tells us the root of the tree is a node, > > so the comment is correct but maybe you have a better way of expressing > > this information? > > Hmm. Can you please correct me on my understanding - when we have an > empty tree, then we insert a root and can store a value there. Now when > we store the second entry, we allocate a node and make the root a node, > the root points to that node, and we store the values at offsets 0 and 1. > > I am reading more to answer my own question. Not quite. If we store to 0 of size 1, then we can just have a pointer without a node at all. There are a few scenarios which can play out when storing the first entry to the tree: Nothing stored, root is NULL, representing 0 - ULONG_MAX => NULL There is a value only at zero, root is the entry, representing 0. 1 - ULONG_MAX => NULL. To ensure that the root entry isn't detected as a node, there are restrictions on the entry value. There is a value only at zero which would be confused with a node. A node is allocated and the ranges are stored in the node. 0 => entry and 1 - ULONG_MAX => NULL. There is a value that is not just zero (and may not include zero in the range), then a node is stored at root. Read mas_store_root() for details. As the tree grows and shrinks, the type of node stored in the root may change. The root may return to just a pointer or NULL. Once there is a node at root, each slot either contains an entry/NULL or a child node. Each pivot defines a maximum for the range while the previous pivot (or the minimum of that node, starting at 0) defines the minimum. So the [minimum] = start of range 0, pivot[0] = end of range zero, pivot[0] + 1 = start of range 1, etc. Nodes do not store the minimum and may not store the maximum (if there isn't enough pivots the maximum is just inherited from the parent node). All ranges are represented and present at the child node. This means that ever range will walk to the leaf node and have an entry or NULL. B-trees require everything to be at the same height. So, the entries at offsets 0 and 1 depend on the ranges stored. You can see a diagram of a node in ascii at the top of lib/maple_tree.c as well as terminology used. I have tried to keep the developer documentation in the .c and .h files, while the user documentation is in Documentation/core-api/maple_tree.rst If you read the start of the .c, it runs through a node layout. I've also posted an overview of the tree on the Oracle Blog [1] and given a talk about some of the way the tree worked for the Linux Foundation [2]. You can also find talks at OSS 2019 by willy, and lpc 2019 by myself as well as 2022, and lsf/mm if you search for 'maple tree linux' on youtube. Hopefully that helps. [1] https://blogs.oracle.com/linux/post/maple-tree-storing-ranges [2] https://www.linuxfoundation.org/webinars/the-maple-tree-structure-and-algorithms?hsLang=en Thanks, Liam ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 2/2] maple tree: Add and fix some comments 2025-07-03 5:54 ` Liam R. Howlett @ 2025-07-03 6:14 ` Dev Jain 0 siblings, 0 replies; 10+ messages in thread From: Dev Jain @ 2025-07-03 6:14 UTC (permalink / raw) To: Liam R. Howlett, akpm, richard.weiyang, maple-tree, linux-mm, linux-kernel On 03/07/25 11:24 am, Liam R. Howlett wrote: > * Dev Jain <dev.jain@arm.com> [250628 07:57]: >> On 27/06/25 1:34 am, Liam R. Howlett wrote: >>> * Dev Jain <dev.jain@arm.com> [250626 13:19]: >>>> Add comments explaining the fields for maple_metadata, since "end" is >>>> ambiguous and "gap" can be confused as the largest gap, whereas it >>>> is actually the offset of the largest gap. >>>> >>>> MAPLE_ROOT_NODE is used for mt_mk_root() and mt_safe_root(), indicating >>>> that it is used to mark the node as root. So fix the comment. >>> That's not quite the entire story here. >>> >>> The first pointer in the tree may not be a node at all, and may be an >>> entry. So having that bit set tells us the root of the tree is a node, >>> so the comment is correct but maybe you have a better way of expressing >>> this information? >> Hmm. Can you please correct me on my understanding - when we have an >> empty tree, then we insert a root and can store a value there. Now when >> we store the second entry, we allocate a node and make the root a node, >> the root points to that node, and we store the values at offsets 0 and 1. >> >> I am reading more to answer my own question. > Not quite. > > If we store to 0 of size 1, then we can just have a pointer without a > node at all. There are a few scenarios which can play out when storing > the first entry to the tree: > > Nothing stored, root is NULL, representing 0 - ULONG_MAX => NULL > > There is a value only at zero, root is the entry, representing 0. > 1 - ULONG_MAX => NULL. To ensure that the root entry isn't detected as > a node, there are restrictions on the entry value. > > There is a value only at zero which would be confused with a node. A > node is allocated and the ranges are stored in the node. 0 => entry and > 1 - ULONG_MAX => NULL. > > There is a value that is not just zero (and may not include zero in the > range), then a node is stored at root. > > Read mas_store_root() for details. > > As the tree grows and shrinks, the type of node stored in the root may > change. The root may return to just a pointer or NULL. > > Once there is a node at root, each slot either contains an entry/NULL or > a child node. Each pivot defines a maximum for the range while the > previous pivot (or the minimum of that node, starting at 0) defines the > minimum. So the [minimum] = start of range 0, pivot[0] = end of range > zero, pivot[0] + 1 = start of range 1, etc. > > Nodes do not store the minimum and may not store the maximum (if there > isn't enough pivots the maximum is just inherited from the parent node). > > All ranges are represented and present at the child node. This means > that ever range will walk to the leaf node and have an entry or NULL. > B-trees require everything to be at the same height. > > So, the entries at offsets 0 and 1 depend on the ranges stored. > > You can see a diagram of a node in ascii at the top of lib/maple_tree.c > as well as terminology used. > > I have tried to keep the developer documentation in the .c and .h files, > while the user documentation is in Documentation/core-api/maple_tree.rst > > If you read the start of the .c, it runs through a node layout. > > I've also posted an overview of the tree on the Oracle Blog [1] and > given a talk about some of the way the tree worked for the Linux > Foundation [2]. You can also find talks at OSS 2019 by willy, and lpc > 2019 by myself as well as 2022, and lsf/mm if you search for 'maple tree > linux' on youtube. > > Hopefully that helps. > > [1] https://blogs.oracle.com/linux/post/maple-tree-storing-ranges > [2] https://www.linuxfoundation.org/webinars/the-maple-tree-structure-and-algorithms?hsLang=en > > Thanks, > Liam Thanks for your reply, I have already seen all of the above mentioned resources : ) ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] maple tree: Clean up mtree_range_walk() 2025-06-26 17:19 [PATCH 1/2] maple tree: Clean up mtree_range_walk() Dev Jain 2025-06-26 17:19 ` [PATCH 2/2] maple tree: Add and fix some comments Dev Jain @ 2025-06-26 19:58 ` Liam R. Howlett 2025-06-28 11:57 ` Dev Jain 1 sibling, 1 reply; 10+ messages in thread From: Liam R. Howlett @ 2025-06-26 19:58 UTC (permalink / raw) To: Dev Jain; +Cc: akpm, richard.weiyang, maple-tree, linux-mm, linux-kernel * Dev Jain <dev.jain@arm.com> [250626 13:19]: > The special casing for offset == 0 is being done because min will stay > mas->min in this case. So refactor the code to use the while loop for > setting the max and getting the corresponding offset, and only set the > min for offset > 0. > > Signed-off-by: Dev Jain <dev.jain@arm.com> > --- > lib/maple_tree.c | 11 +++-------- > 1 file changed, 3 insertions(+), 8 deletions(-) > > diff --git a/lib/maple_tree.c b/lib/maple_tree.c > index 0e85e92c5375..6c89e6790fb5 100644 > --- a/lib/maple_tree.c > +++ b/lib/maple_tree.c > @@ -2770,13 +2770,8 @@ static inline void *mtree_range_walk(struct ma_state *mas) > end = ma_data_end(node, type, pivots, max); > prev_min = min; > prev_max = max; > - if (pivots[0] >= mas->index) { > - offset = 0; > - max = pivots[0]; > - goto next; > - } > This new line should be dropped. > - offset = 1; > + offset = 0; > while (offset < end) { This should now be a do {} while(); > if (pivots[offset] >= mas->index) { > max = pivots[offset]; > @@ -2784,9 +2779,9 @@ static inline void *mtree_range_walk(struct ma_state *mas) > } > offset++; > } There should be a new line here. > + if (likely(offset)) > + min = pivots[offset - 1] + 1; > > - min = pivots[offset - 1] + 1; > -next: > slots = ma_slots(node, type); > next = mt_slot(mas->tree, slots, offset); > if (unlikely(ma_dead_node(node))) > -- > 2.30.2 > The current way will check pivot 0, then skip the main loop. Pivot 0 has an equal chance of being the range you are looking for, but that probability increases based on a lower number of entries in the node. The root node, which we always pass through, can have as little as two entries, so then it's 50/50 you want pivot 0. With the way you've written it, it will check offset < end (which will always be the case for the first time), then do the same work as the out-of-loop check, then check offset an extra time after the loop. If it's written with a do {} while, the initial check of offset < end is avoided, but you will end up checking offset an extra time to see if min needs to be set. If pivot 0 is NOT the entry you want, then the current code will check pivot 0, then execute the loop one less time. In the even of a root node with 2 entries, it will not enter the loop at all. So, the way it is written is less code execution by avoiding unnecessary assignment of min and checks (of offset == 0 and offset < end). Thanks, Liam ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] maple tree: Clean up mtree_range_walk() 2025-06-26 19:58 ` [PATCH 1/2] maple tree: Clean up mtree_range_walk() Liam R. Howlett @ 2025-06-28 11:57 ` Dev Jain 2025-07-03 6:00 ` Liam R. Howlett 0 siblings, 1 reply; 10+ messages in thread From: Dev Jain @ 2025-06-28 11:57 UTC (permalink / raw) To: Liam R. Howlett, akpm, richard.weiyang, maple-tree, linux-mm, linux-kernel On 27/06/25 1:28 am, Liam R. Howlett wrote: > * Dev Jain <dev.jain@arm.com> [250626 13:19]: >> The special casing for offset == 0 is being done because min will stay >> mas->min in this case. So refactor the code to use the while loop for >> setting the max and getting the corresponding offset, and only set the >> min for offset > 0. >> >> Signed-off-by: Dev Jain <dev.jain@arm.com> >> --- >> lib/maple_tree.c | 11 +++-------- >> 1 file changed, 3 insertions(+), 8 deletions(-) >> >> diff --git a/lib/maple_tree.c b/lib/maple_tree.c >> index 0e85e92c5375..6c89e6790fb5 100644 >> --- a/lib/maple_tree.c >> +++ b/lib/maple_tree.c >> @@ -2770,13 +2770,8 @@ static inline void *mtree_range_walk(struct ma_state *mas) >> end = ma_data_end(node, type, pivots, max); >> prev_min = min; >> prev_max = max; >> - if (pivots[0] >= mas->index) { >> - offset = 0; >> - max = pivots[0]; >> - goto next; >> - } >> > This new line should be dropped. > >> - offset = 1; >> + offset = 0; >> while (offset < end) { > This should now be a do {} while(); > >> if (pivots[offset] >= mas->index) { >> max = pivots[offset]; >> @@ -2784,9 +2779,9 @@ static inline void *mtree_range_walk(struct ma_state *mas) >> } >> offset++; >> } > There should be a new line here. > >> + if (likely(offset)) >> + min = pivots[offset - 1] + 1; >> >> - min = pivots[offset - 1] + 1; >> -next: >> slots = ma_slots(node, type); >> next = mt_slot(mas->tree, slots, offset); >> if (unlikely(ma_dead_node(node))) >> -- >> 2.30.2 >> > The current way will check pivot 0, then skip the main loop. Pivot 0 > has an equal chance of being the range you are looking for, but that > probability increases based on a lower number of entries in the node. > The root node, which we always pass through, can have as little as two > entries, so then it's 50/50 you want pivot 0. My understanding of the tree currently is that ma_root is a single slot. Or can it be a normal node with 31 slots? > > With the way you've written it, it will check offset < end (which will > always be the case for the first time), then do the same work as the > out-of-loop check, then check offset an extra time after the loop. > > If it's written with a do {} while, the initial check of offset < end is > avoided, but you will end up checking offset an extra time to see if min > needs to be set. > > If pivot 0 is NOT the entry you want, then the current code will check > pivot 0, then execute the loop one less time. In the even of a root > node with 2 entries, it will not enter the loop at all. > > So, the way it is written is less code execution by avoiding unnecessary > assignment of min and checks (of offset == 0 and offset < end). Thank you for your detailed explanation. I will have to read more to understand what you have written : ) > > Thanks, > Liam ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] maple tree: Clean up mtree_range_walk() 2025-06-28 11:57 ` Dev Jain @ 2025-07-03 6:00 ` Liam R. Howlett 0 siblings, 0 replies; 10+ messages in thread From: Liam R. Howlett @ 2025-07-03 6:00 UTC (permalink / raw) To: Dev Jain; +Cc: akpm, richard.weiyang, maple-tree, linux-mm, linux-kernel * Dev Jain <dev.jain@arm.com> [250628 07:59]: > > On 27/06/25 1:28 am, Liam R. Howlett wrote: > > * Dev Jain <dev.jain@arm.com> [250626 13:19]: > > > The special casing for offset == 0 is being done because min will stay > > > mas->min in this case. So refactor the code to use the while loop for > > > setting the max and getting the corresponding offset, and only set the > > > min for offset > 0. > > > > > > Signed-off-by: Dev Jain <dev.jain@arm.com> > > > --- > > > lib/maple_tree.c | 11 +++-------- > > > 1 file changed, 3 insertions(+), 8 deletions(-) > > > > > > diff --git a/lib/maple_tree.c b/lib/maple_tree.c > > > index 0e85e92c5375..6c89e6790fb5 100644 > > > --- a/lib/maple_tree.c > > > +++ b/lib/maple_tree.c > > > @@ -2770,13 +2770,8 @@ static inline void *mtree_range_walk(struct ma_state *mas) > > > end = ma_data_end(node, type, pivots, max); > > > prev_min = min; > > > prev_max = max; > > > - if (pivots[0] >= mas->index) { > > > - offset = 0; > > > - max = pivots[0]; > > > - goto next; > > > - } > > This new line should be dropped. > > > > > - offset = 1; > > > + offset = 0; > > > while (offset < end) { > > This should now be a do {} while(); > > > > > if (pivots[offset] >= mas->index) { > > > max = pivots[offset]; > > > @@ -2784,9 +2779,9 @@ static inline void *mtree_range_walk(struct ma_state *mas) > > > } > > > offset++; > > > } > > There should be a new line here. > > > > > + if (likely(offset)) > > > + min = pivots[offset - 1] + 1; > > > - min = pivots[offset - 1] + 1; > > > -next: > > > slots = ma_slots(node, type); > > > next = mt_slot(mas->tree, slots, offset); > > > if (unlikely(ma_dead_node(node))) > > > -- > > > 2.30.2 > > > > > The current way will check pivot 0, then skip the main loop. Pivot 0 > > has an equal chance of being the range you are looking for, but that > > probability increases based on a lower number of entries in the node. > > The root node, which we always pass through, can have as little as two > > entries, so then it's 50/50 you want pivot 0. > > My understanding of the tree currently is that ma_root is a single slot. > Or can it be a normal node with 31 slots? Ah.. ma_root is a pointer which could be a node, null, or an entry. We won't get here with a NULL or an entry.. because we don't need to walk those. So at this point, we are entering with a node which could currently be two types; arange64 or range64. Cheers, Liam ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2025-07-03 6:15 UTC | newest] Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2025-06-26 17:19 [PATCH 1/2] maple tree: Clean up mtree_range_walk() Dev Jain 2025-06-26 17:19 ` [PATCH 2/2] maple tree: Add and fix some comments Dev Jain 2025-06-26 20:04 ` Liam R. Howlett 2025-06-28 11:56 ` Dev Jain 2025-06-29 23:16 ` Wei Yang 2025-07-03 5:54 ` Liam R. Howlett 2025-07-03 6:14 ` Dev Jain 2025-06-26 19:58 ` [PATCH 1/2] maple tree: Clean up mtree_range_walk() Liam R. Howlett 2025-06-28 11:57 ` Dev Jain 2025-07-03 6:00 ` Liam R. Howlett
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox