linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
From: Joonsoo Kim <iamjoonsoo.kim@lge.com>
To: Christoph Lameter <cl@linux.com>
Cc: Pekka Enberg <penberg@kernel.org>,
	Glauber Costa <glommer@parallels.com>,
	linux-mm@kvack.org, David Rientjes <rientjes@google.com>
Subject: Re: [3.11 1/4] slub: Make cpu partial slab support configurable V2
Date: Wed, 19 Jun 2013 14:22:03 +0900	[thread overview]
Message-ID: <20130619052203.GA12231@lge.com> (raw)
In-Reply-To: <0000013f44418a14-7abe9784-a481-4c34-8ff3-c3afe2d57979-000000@email.amazonses.com>

Hello, Christoph.

On Fri, Jun 14, 2013 at 07:55:13PM +0000, Christoph Lameter wrote:
> cpu partial support can introduce level of indeterminism that is not wanted
> in certain context (like a realtime kernel). Make it configurable.
> 
> Signed-off-by: Christoph Lameter <cl@linux.com>
> 
> Index: linux/include/linux/slub_def.h
> ===================================================================
> --- linux.orig/include/linux/slub_def.h	2013-06-14 09:50:58.190453865 -0500
> +++ linux/include/linux/slub_def.h	2013-06-14 09:50:58.186453794 -0500
> @@ -73,7 +73,9 @@ struct kmem_cache {
>  	int size;		/* The size of an object including meta data */
>  	int object_size;	/* The size of an object without meta data */
>  	int offset;		/* Free pointer offset. */
> +#ifdef CONFIG_SLUB_CPU_PARTIAL
>  	int cpu_partial;	/* Number of per cpu partial objects to keep around */
> +#endif
>  	struct kmem_cache_order_objects oo;
>  
>  	/* Allocation and freeing of slabs */
> @@ -104,6 +106,15 @@ struct kmem_cache {
>  	struct kmem_cache_node *node[MAX_NUMNODES];
>  };

How about maintaining cpu_partial when !CONFIG_SLUB_CPU_PARTIAL?
It makes code less churn and doesn't have much overhead.
At bottom, my implementation with cpu_partial is attached. It uses less '#ifdef'.

>  
> +static inline int kmem_cache_cpu_partial(struct kmem_cache *s)
> +{
> +#ifdef CONFIG_SLUB_CPU_PARTIAL
> +	return s->cpu_partial;
> +#else
> +	return 0;
> +#endif
> +}
> +
>  void *kmem_cache_alloc(struct kmem_cache *, gfp_t);
>  void *__kmalloc(size_t size, gfp_t flags);
>  
> Index: linux/mm/slub.c
> ===================================================================
> --- linux.orig/mm/slub.c	2013-06-14 09:50:58.190453865 -0500
> +++ linux/mm/slub.c	2013-06-14 09:50:58.186453794 -0500
> @@ -1573,7 +1573,8 @@ static void *get_partial_node(struct kme
>  			put_cpu_partial(s, page, 0);
>  			stat(s, CPU_PARTIAL_NODE);
>  		}
> -		if (kmem_cache_debug(s) || available > s->cpu_partial / 2)
> +		if (kmem_cache_debug(s) ||
> +			       available > kmem_cache_cpu_partial(s) / 2)
>  			break;
>  
>  	}
> @@ -1884,6 +1885,7 @@ redo:
>  static void unfreeze_partials(struct kmem_cache *s,
>  		struct kmem_cache_cpu *c)
>  {
> +#ifdef CONFIG_SLUB_CPU_PARTIAL
>  	struct kmem_cache_node *n = NULL, *n2 = NULL;
>  	struct page *page, *discard_page = NULL;
>  
> @@ -1938,6 +1940,7 @@ static void unfreeze_partials(struct kme
>  		discard_slab(s, page);
>  		stat(s, FREE_SLAB);
>  	}
> +#endif
>  }
>  
>  /*
> @@ -1951,6 +1954,7 @@ static void unfreeze_partials(struct kme
>   */
>  static void put_cpu_partial(struct kmem_cache *s, struct page *page, int drain)
>  {
> +#ifdef CONFIG_SLUB_CPU_PARTIAL
>  	struct page *oldpage;
>  	int pages;
>  	int pobjects;
> @@ -1987,6 +1991,7 @@ static void put_cpu_partial(struct kmem_
>  		page->next = oldpage;
>  
>  	} while (this_cpu_cmpxchg(s->cpu_slab->partial, oldpage, page) != oldpage);
> +#endif
>  }
>  
>  static inline void flush_slab(struct kmem_cache *s, struct kmem_cache_cpu *c)
> @@ -2495,6 +2500,7 @@ static void __slab_free(struct kmem_cach
>  		new.inuse--;
>  		if ((!new.inuse || !prior) && !was_frozen) {
>  
> +#ifdef CONFIG_SLUB_CPU_PARTIAL
>  			if (!kmem_cache_debug(s) && !prior)
>  
>  				/*
> @@ -2503,7 +2509,9 @@ static void __slab_free(struct kmem_cach
>  				 */
>  				new.frozen = 1;
>  
> -			else { /* Needs to be taken off a list */
> +			else
> +#endif
> +		       		{ /* Needs to be taken off a list */
>  
>  	                        n = get_node(s, page_to_nid(page));
>  				/*
> @@ -2525,6 +2533,7 @@ static void __slab_free(struct kmem_cach
>  		"__slab_free"));
>  
>  	if (likely(!n)) {
> +#ifdef CONFIG_SLUB_CPU_PARTIAL
>  
>  		/*
>  		 * If we just froze the page then put it onto the
> @@ -2534,6 +2543,7 @@ static void __slab_free(struct kmem_cach
>  			put_cpu_partial(s, page, 1);
>  			stat(s, CPU_PARTIAL_FREE);
>  		}
> +#endif
>  		/*
>  		 * The list lock was not taken therefore no list
>  		 * activity can be necessary.
> @@ -3041,7 +3051,7 @@ static int kmem_cache_open(struct kmem_c
>  	 * list to avoid pounding the page allocator excessively.
>  	 */
>  	set_min_partial(s, ilog2(s->size) / 2);
> -
> +#ifdef CONFIG_SLUB_CPU_PARTIAL
>  	/*
>  	 * cpu_partial determined the maximum number of objects kept in the
>  	 * per cpu partial lists of a processor.
> @@ -3069,6 +3079,7 @@ static int kmem_cache_open(struct kmem_c
>  		s->cpu_partial = 13;
>  	else
>  		s->cpu_partial = 30;
> +#endif
>  
>  #ifdef CONFIG_NUMA
>  	s->remote_node_defrag_ratio = 1000;
> @@ -4424,7 +4435,7 @@ SLAB_ATTR(order);
>  
>  static ssize_t min_partial_show(struct kmem_cache *s, char *buf)
>  {
> -	return sprintf(buf, "%lu\n", s->min_partial);
> +	return sprintf(buf, "%u\n", kmem_cache_cpu_partial(s));
>  }

min_partial is not related to cpu_partial.

>  
>  static ssize_t min_partial_store(struct kmem_cache *s, const char *buf,
> @@ -4444,7 +4455,7 @@ SLAB_ATTR(min_partial);
>  
>  static ssize_t cpu_partial_show(struct kmem_cache *s, char *buf)
>  {
> -	return sprintf(buf, "%u\n", s->cpu_partial);
> +	return sprintf(buf, "%u\n", kmem_cache_cpu_partial(s));
>  }
>  
>  static ssize_t cpu_partial_store(struct kmem_cache *s, const char *buf,
> @@ -4458,10 +4469,13 @@ static ssize_t cpu_partial_store(struct
>  		return err;
>  	if (objects && kmem_cache_debug(s))
>  		return -EINVAL;
> -
> +#ifdef CONFIG_SLUB_CPU_PARTIAL
>  	s->cpu_partial = objects;
>  	flush_all(s);
>  	return length;
> +#else
> +	return -ENOSYS;
> +#endif
>  }
>  SLAB_ATTR(cpu_partial);
>  
> Index: linux/init/Kconfig
> ===================================================================
> --- linux.orig/init/Kconfig	2013-06-14 09:50:58.190453865 -0500
> +++ linux/init/Kconfig	2013-06-14 09:50:58.186453794 -0500
> @@ -1559,6 +1559,17 @@ config SLOB
>  
>  endchoice
>  
> +config SLUB_CPU_PARTIAL
> +	default y
> +	depends on SLUB
> +	bool "SLUB per cpu partial cache"
> +	help
> +	  Per cpu partial caches accellerate objects allocation and freeing
> +	  that is local to a processor at the price of more indeterminism
> +	  in the latency of the free. On overflow these caches will be cleared
> +	  which requires the taking of locks that may cause latency spikes.
> +	  Typically one would choose no for a realtime system.
> +
>  config MMAP_ALLOW_UNINITIALIZED
>  	bool "Allow mmapped anonymous memory to be uninitialized"
>  	depends on EXPERT && !MMU
> 
> --
> To unsubscribe, send a message with 'unsubscribe linux-mm' in
> the body to majordomo@kvack.org.  For more info on Linux MM,
> see: http://www.linux-mm.org/ .
> Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>


-----------------------8<---------------------------
diff --git a/init/Kconfig b/init/Kconfig
index 2d9b831..a7ec1ec 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1559,6 +1559,17 @@ config SLOB
 
 endchoice
 
+config SLUB_CPU_PARTIAL
+	default y
+	depends on SLUB
+	bool "SLUB per cpu partial cache"
+	help
+	  Per cpu partial caches accellerate objects allocation and freeing
+	  that is local to a processor at the price of more indeterminism
+	  in the latency of the free. On overflow these caches will be cleared
+	  which requires the taking of locks that may cause latency spikes.
+	  Typically one would choose no for a realtime system.
+
 config MMAP_ALLOW_UNINITIALIZED
 	bool "Allow mmapped anonymous memory to be uninitialized"
 	depends on EXPERT && !MMU
diff --git a/mm/slub.c b/mm/slub.c
index 57707f0..c820f9d 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -123,6 +123,15 @@ static inline int kmem_cache_debug(struct kmem_cache *s)
 #endif
 }
 
+static inline int kmem_cache_has_cpu_partial(struct kmem_cache *s)
+{
+#ifdef CONFIG_SLUB_PARTIAL
+	return !kmem_cache_debug(s);
+#else
+	return false;
+#endif
+}
+
 /*
  * Issues still to be resolved:
  *
@@ -1573,7 +1582,8 @@ static void *get_partial_node(struct kmem_cache *s, struct kmem_cache_node *n,
 			put_cpu_partial(s, page, 0);
 			stat(s, CPU_PARTIAL_NODE);
 		}
-		if (kmem_cache_debug(s) || available > s->cpu_partial / 2)
+		if (!kmem_cache_has_cpu_partial(s)
+			|| available > s->cpu_partial / 2)
 			break;
 
 static void unfreeze_partials(struct kmem_cache *s,
 		struct kmem_cache_cpu *c)
 {
+#ifdef CONFIG_SLUB_PARTIAL
 	struct kmem_cache_node *n = NULL, *n2 = NULL;
 	struct page *page, *discard_page = NULL;
 
@@ -1938,6 +1949,7 @@ static void unfreeze_partials(struct kmem_cache *s,
 		discard_slab(s, page);
 		stat(s, FREE_SLAB);
 	}
+#endif
 }
 
 /*
@@ -1951,6 +1963,7 @@ static void unfreeze_partials(struct kmem_cache *s,
  */
 static void put_cpu_partial(struct kmem_cache *s, struct page *page, int drain)
 {
+#ifdef CONFIG_SLUB_PARTIAL
 	struct page *oldpage;
 	int pages;
 	int pobjects;
@@ -1987,6 +2000,7 @@ static void put_cpu_partial(struct kmem_cache *s, struct page *page, int drain)
 		page->next = oldpage;
 
 	} while (this_cpu_cmpxchg(s->cpu_slab->partial, oldpage, page) != oldpage);
+#endif
 }
 
 static inline void flush_slab(struct kmem_cache *s, struct kmem_cache_cpu *c)
@@ -2495,7 +2509,7 @@ static void __slab_free(struct kmem_cache *s, struct page *page,
 		new.inuse--;
 		if ((!new.inuse || !prior) && !was_frozen) {
 
-			if (!kmem_cache_debug(s) && !prior)
+			if (kmem_cache_has_cpu_partial(s) && !prior)
 
 				/*
 				 * Slab was on no list before and will be partially empty
@@ -3059,7 +3073,7 @@ static int kmem_cache_open(struct kmem_cache *s, unsigned long flags)
 	 *    per node list when we run out of per cpu objects. We only fetch 50%
 	 *    to keep some capacity around for frees.
 	 */
-	if (kmem_cache_debug(s))
+	if (!kmem_cache_has_cpu_partial(s))
 		s->cpu_partial = 0;
 	else if (s->size >= PAGE_SIZE)
 		s->cpu_partial = 2;
@@ -4456,7 +4470,7 @@ static ssize_t cpu_partial_store(struct kmem_cache *s, const char *buf,
 	err = strict_strtoul(buf, 10, &objects);
 	if (err)
 		return err;
-	if (objects && kmem_cache_debug(s))
+	if (objects && !kmem_cache_has_cpu_partial(s))
 		return -EINVAL;
 
 	s->cpu_partial = objects;
-- 
1.7.9.5


--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

  parent reply	other threads:[~2013-06-19  5:21 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20130614195500.373711648@linux.com>
2013-06-14 19:55 ` [3.11 1/4] slub: Make cpu partial slab support configurable V2 Christoph Lameter
2013-06-18  6:35   ` Pekka Enberg
2013-06-18 14:17     ` Christoph Lameter
2013-06-18 15:21       ` Clark Williams
2013-06-18 15:25         ` Pekka Enberg
2013-06-25 14:24           ` Steven Rostedt
2013-07-01 18:16             ` Christoph Lameter
2013-07-02 15:09               ` Clark Williams
2013-07-02 16:47                 ` Christoph Lameter
2013-07-02 16:53                   ` Clark Williams
2013-07-17  2:46                   ` Steven Rostedt
2013-07-17  7:04                     ` Pekka Enberg
2013-07-17 12:23                       ` Steven Rostedt
2013-07-17 15:04                         ` Christoph Lameter
2013-07-17 15:15                           ` Steven Rostedt
2013-07-17 15:24                             ` Steven Rostedt
2013-06-19  5:22   ` Joonsoo Kim [this message]
2013-06-19 14:29     ` Christoph Lameter
2013-06-20  1:50       ` Joonsoo Kim
2013-06-20  2:53         ` Wanpeng Li
2013-06-20  2:53         ` Wanpeng Li
     [not found]         ` <51c26ebd.e842320a.5dc1.ffffedfcSMTPIN_ADDED_BROKEN@mx.google.com>
2013-06-20  5:45           ` Joonsoo Kim
2013-06-20  5:50         ` Joonsoo Kim
2013-07-07 16:10           ` Pekka Enberg
2013-06-14 19:55 ` [3.11 2/4] slob: Rework #ifdeffery in slab.h Christoph Lameter
2013-06-14 20:06 ` [3.11 3/4] Move kmalloc_node functions to common code Christoph Lameter
2013-06-18 15:38   ` Pekka Enberg
2013-06-18 17:02     ` Christoph Lameter
2013-07-07 16:14       ` Pekka Enberg
2013-07-08 18:55         ` Christoph Lameter
2013-06-19  6:30   ` Joonsoo Kim
2013-06-19 14:33     ` Christoph Lameter
2013-06-20  1:51       ` Joonsoo Kim
2013-06-14 20:06 ` [3.11 4/4] Move kmalloc definitions to slab.h Christoph Lameter

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20130619052203.GA12231@lge.com \
    --to=iamjoonsoo.kim@lge.com \
    --cc=cl@linux.com \
    --cc=glommer@parallels.com \
    --cc=linux-mm@kvack.org \
    --cc=penberg@kernel.org \
    --cc=rientjes@google.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).