diff mbox

[net-next,2/2] rhashtable: Quick initial growth of tables

Message ID 1430434005-6143-3-git-send-email-tgraf@suug.ch
State Changes Requested, archived
Delegated to: David Miller
Headers show

Commit Message

Thomas Graf April 30, 2015, 10:46 p.m. UTC
Grow the table quicker than 2x in the beginning to avoid long chains
of rehashes. The effect is observable in the self-test where table
jumps are reduced to a minimum after a lot of entries have been added
in a short period of time. The iterator is able to get a consistent
view most of the time.

Signed-off-by: Thomas Graf <tgraf@suug.ch>
---
 lib/rhashtable.c | 37 +++++++++++++++++++++++++++++++++++--
 1 file changed, 35 insertions(+), 2 deletions(-)

Comments

Herbert Xu April 30, 2015, 11:45 p.m. UTC | #1
Thomas Graf <tgraf@suug.ch> wrote:
> Grow the table quicker than 2x in the beginning to avoid long chains
> of rehashes. The effect is observable in the self-test where table
> jumps are reduced to a minimum after a lot of entries have been added
> in a short period of time. The iterator is able to get a consistent
> view most of the time.
> 
> Signed-off-by: Thomas Graf <tgraf@suug.ch>

Wouldn't automatic shrinking immediately undo your quick growth?

Cheers,
Thomas Graf May 1, 2015, 4:30 a.m. UTC | #2
On 05/01/15 at 07:45am, Herbert Xu wrote:
> Thomas Graf <tgraf@suug.ch> wrote:
> > Grow the table quicker than 2x in the beginning to avoid long chains
> > of rehashes. The effect is observable in the self-test where table
> > jumps are reduced to a minimum after a lot of entries have been added
> > in a short period of time. The iterator is able to get a consistent
> > view most of the time.
> > 
> > Signed-off-by: Thomas Graf <tgraf@suug.ch>
> 
> Wouldn't automatic shrinking immediately undo your quick growth?

Yes, that can happen. Since shrinks are ordered to the end of the
chain it is often the case that enough entries have been added so the
shrink is not carried out in the end. Obviously this is also not the
case if no entries are actually removed.

What about we apply quick growing on >100% utilization? It is a
clear indication that we are growing rapidly.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Herbert Xu May 1, 2015, 4:37 a.m. UTC | #3
On Fri, May 01, 2015 at 06:30:25AM +0200, Thomas Graf wrote:
>
> Yes, that can happen. Since shrinks are ordered to the end of the
> chain it is often the case that enough entries have been added so the
> shrink is not carried out in the end. Obviously this is also not the
> case if no entries are actually removed.

It's just a matter of logical consistency.  At 75% if you grow by
a factor of 4, you get 18.75% utilisation which is way below the
30% shrink threshold.

> What about we apply quick growing on >100% utilization? It is a
> clear indication that we are growing rapidly.

Even at 100%, a factor of 4 leads you to 25% which is less than 30%.

Perhaps we could lower the shrink thresholds? Alternatively, only
grow quickly if automatic shrinking is disabled.  After all, the one
case that's inspring all of this, netlink really wants to grow
quickly as well as only shrink at specific points in time.

Cheers,
Sergei Shtylyov May 1, 2015, 11:04 a.m. UTC | #4
Hello.

On 5/1/2015 1:46 AM, Thomas Graf wrote:

> Grow the table quicker than 2x in the beginning to avoid long chains
> of rehashes. The effect is observable in the self-test where table
> jumps are reduced to a minimum after a lot of entries have been added
> in a short period of time. The iterator is able to get a consistent
> view most of the time.

> Signed-off-by: Thomas Graf <tgraf@suug.ch>
> ---
>   lib/rhashtable.c | 37 +++++++++++++++++++++++++++++++++++--
>   1 file changed, 35 insertions(+), 2 deletions(-)

> diff --git a/lib/rhashtable.c b/lib/rhashtable.c
> index 4936fc4..23e7f18 100644
> --- a/lib/rhashtable.c
> +++ b/lib/rhashtable.c
> @@ -271,6 +271,38 @@ static int rhashtable_rehash_table(struct rhashtable *ht)
>   	return rht_dereference(new_tbl->future_tbl, ht) ? -EAGAIN : 0;
>   }
>
> +static int table_growth_log(unsigned int size)
> +{
> +	/*
> +	 * Table growth:
> +	 *     2 ->   64
> +	 *     4 ->  128
> +	 *     8 ->  128
> +	 *    16 ->  256
> +	 *    32 ->  512
> +	 *    64 ->  512
> +	 *   128 -> 1024
> +	 *   256 -> 2048
> +	 *   512 -> 2048
> +	 *  1024 -> 4096
> +	 *  2048 -> 8192
> +	 *  4096 -> 8192
> +	 */
> +	int log = 5 - (ilog2(size) / 3);
> +
> +	return log > 1 ? log : 1;

    max(log, 1)?

[...]

WBR, Sergei

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Thomas Graf May 1, 2015, 1:38 p.m. UTC | #5
On 05/01/15 at 12:37pm, Herbert Xu wrote:
> On Fri, May 01, 2015 at 06:30:25AM +0200, Thomas Graf wrote:
> >
> > Yes, that can happen. Since shrinks are ordered to the end of the
> > chain it is often the case that enough entries have been added so the
> > shrink is not carried out in the end. Obviously this is also not the
> > case if no entries are actually removed.
> 
> It's just a matter of logical consistency.  At 75% if you grow by
> a factor of 4, you get 18.75% utilisation which is way below the
> 30% shrink threshold.
> 
> > What about we apply quick growing on >100% utilization? It is a
> > clear indication that we are growing rapidly.
> 
> Even at 100%, a factor of 4 leads you to 25% which is less than 30%.
> 
> Perhaps we could lower the shrink thresholds? Alternatively, only
> grow quickly if automatic shrinking is disabled.  After all, the one
> case that's inspring all of this, netlink really wants to grow
> quickly as well as only shrink at specific points in time.

Lowering the shrink threshold in combination with quick growth
above 100% sounds good to me. The whole point of this is to detect
when we are likely to see a lot of inserts with only a few or no
removals.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Thomas Graf May 1, 2015, 1:38 p.m. UTC | #6
On 05/01/15 at 02:04pm, Sergei Shtylyov wrote:
> >+	return log > 1 ? log : 1;
> 
>    max(log, 1)?

Sure
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/lib/rhashtable.c b/lib/rhashtable.c
index 4936fc4..23e7f18 100644
--- a/lib/rhashtable.c
+++ b/lib/rhashtable.c
@@ -271,6 +271,38 @@  static int rhashtable_rehash_table(struct rhashtable *ht)
 	return rht_dereference(new_tbl->future_tbl, ht) ? -EAGAIN : 0;
 }
 
+static int table_growth_log(unsigned int size)
+{
+	/*
+	 * Table growth:
+	 *     2 ->   64
+	 *     4 ->  128
+	 *     8 ->  128
+	 *    16 ->  256
+	 *    32 ->  512
+	 *    64 ->  512
+	 *   128 -> 1024
+	 *   256 -> 2048
+	 *   512 -> 2048
+	 *  1024 -> 4096
+	 *  2048 -> 8192
+	 *  4096 -> 8192
+	 */
+	int log = 5 - (ilog2(size) / 3);
+
+	return log > 1 ? log : 1;
+}
+
+static unsigned int grow_table(struct rhashtable *ht, unsigned int old_size)
+{
+	unsigned int new_size;
+
+	new_size = old_size << table_growth_log(old_size);
+	new_size = min(new_size, ht->p.max_size);
+
+	return new_size;
+}
+
 /**
  * rhashtable_expand - Expand hash table while allowing concurrent lookups
  * @ht:		the hash table to expand
@@ -295,7 +327,8 @@  static int rhashtable_expand(struct rhashtable *ht)
 
 	old_tbl = rhashtable_last_table(ht, old_tbl);
 
-	new_tbl = bucket_table_alloc(ht, old_tbl->size * 2, GFP_KERNEL);
+	new_tbl = bucket_table_alloc(ht, grow_table(ht, old_tbl->size),
+				     GFP_KERNEL);
 	if (new_tbl == NULL)
 		return -ENOMEM;
 
@@ -404,7 +437,7 @@  int rhashtable_insert_rehash(struct rhashtable *ht)
 	size = tbl->size;
 
 	if (rht_grow_above_75(ht, tbl))
-		size *= 2;
+		size = grow_table(ht, size);
 	/* Do not schedule more than one rehash */
 	else if (old_tbl != tbl)
 		return -EBUSY;