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>
next prev 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 4/4] Move kmalloc definitions to 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
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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.