aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Duyck <alexander.h.duyck@intel.com>2010-05-21 17:41:35 -0400
committerPekka Enberg <penberg@cs.helsinki.fi>2010-05-24 14:11:29 -0400
commit73367bd8eef4f4eb311005886aaa916013073265 (patch)
treed603667689cfea1d8de49fe3c7fada7f6b6eae53
parent7e125f7b9cbfce4101191b8076d606c517a73066 (diff)
slub: move kmem_cache_node into it's own cacheline
This patch is meant to improve the performance of SLUB by moving the local kmem_cache_node lock into it's own cacheline separate from kmem_cache. This is accomplished by simply removing the local_node when NUMA is enabled. On my system with 2 nodes I saw around a 5% performance increase w/ hackbench times dropping from 6.2 seconds to 5.9 seconds on average. I suspect the performance gain would increase as the number of nodes increases, but I do not have the data to currently back that up. Bugzilla-Reference: http://bugzilla.kernel.org/show_bug.cgi?id=15713 Cc: <stable@kernel.org> Reported-by: Alex Shi <alex.shi@intel.com> Tested-by: Alex Shi <alex.shi@intel.com> Acked-by: Yanmin Zhang <yanmin_zhang@linux.intel.com> Acked-by: Christoph Lameter <cl@linux-foundation.org> Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com> Signed-off-by: Pekka Enberg <penberg@cs.helsinki.fi>
-rw-r--r--include/linux/slub_def.h9
-rw-r--r--mm/slub.c33
2 files changed, 14 insertions, 28 deletions
diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h
index 55695c8d2f8a..6ac37664e8fe 100644
--- a/include/linux/slub_def.h
+++ b/include/linux/slub_def.h
@@ -75,12 +75,6 @@ struct kmem_cache {
75 int offset; /* Free pointer offset. */ 75 int offset; /* Free pointer offset. */
76 struct kmem_cache_order_objects oo; 76 struct kmem_cache_order_objects oo;
77 77
78 /*
79 * Avoid an extra cache line for UP, SMP and for the node local to
80 * struct kmem_cache.
81 */
82 struct kmem_cache_node local_node;
83
84 /* Allocation and freeing of slabs */ 78 /* Allocation and freeing of slabs */
85 struct kmem_cache_order_objects max; 79 struct kmem_cache_order_objects max;
86 struct kmem_cache_order_objects min; 80 struct kmem_cache_order_objects min;
@@ -102,6 +96,9 @@ struct kmem_cache {
102 */ 96 */
103 int remote_node_defrag_ratio; 97 int remote_node_defrag_ratio;
104 struct kmem_cache_node *node[MAX_NUMNODES]; 98 struct kmem_cache_node *node[MAX_NUMNODES];
99#else
100 /* Avoid an extra cache line for UP */
101 struct kmem_cache_node local_node;
105#endif 102#endif
106}; 103};
107 104
diff --git a/mm/slub.c b/mm/slub.c
index e46e3129697d..c2d6e6951f33 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -2133,7 +2133,7 @@ static void free_kmem_cache_nodes(struct kmem_cache *s)
2133 2133
2134 for_each_node_state(node, N_NORMAL_MEMORY) { 2134 for_each_node_state(node, N_NORMAL_MEMORY) {
2135 struct kmem_cache_node *n = s->node[node]; 2135 struct kmem_cache_node *n = s->node[node];
2136 if (n && n != &s->local_node) 2136 if (n)
2137 kmem_cache_free(kmalloc_caches, n); 2137 kmem_cache_free(kmalloc_caches, n);
2138 s->node[node] = NULL; 2138 s->node[node] = NULL;
2139 } 2139 }
@@ -2142,33 +2142,22 @@ static void free_kmem_cache_nodes(struct kmem_cache *s)
2142static int init_kmem_cache_nodes(struct kmem_cache *s, gfp_t gfpflags) 2142static int init_kmem_cache_nodes(struct kmem_cache *s, gfp_t gfpflags)
2143{ 2143{
2144 int node; 2144 int node;
2145 int local_node;
2146
2147 if (slab_state >= UP && (s < kmalloc_caches ||
2148 s >= kmalloc_caches + KMALLOC_CACHES))
2149 local_node = page_to_nid(virt_to_page(s));
2150 else
2151 local_node = 0;
2152 2145
2153 for_each_node_state(node, N_NORMAL_MEMORY) { 2146 for_each_node_state(node, N_NORMAL_MEMORY) {
2154 struct kmem_cache_node *n; 2147 struct kmem_cache_node *n;
2155 2148
2156 if (local_node == node) 2149 if (slab_state == DOWN) {
2157 n = &s->local_node; 2150 early_kmem_cache_node_alloc(gfpflags, node);
2158 else { 2151 continue;
2159 if (slab_state == DOWN) { 2152 }
2160 early_kmem_cache_node_alloc(gfpflags, node); 2153 n = kmem_cache_alloc_node(kmalloc_caches,
2161 continue; 2154 gfpflags, node);
2162 }
2163 n = kmem_cache_alloc_node(kmalloc_caches,
2164 gfpflags, node);
2165
2166 if (!n) {
2167 free_kmem_cache_nodes(s);
2168 return 0;
2169 }
2170 2155
2156 if (!n) {
2157 free_kmem_cache_nodes(s);
2158 return 0;
2171 } 2159 }
2160
2172 s->node[node] = n; 2161 s->node[node] = n;
2173 init_kmem_cache_node(n, s); 2162 init_kmem_cache_node(n, s);
2174 } 2163 }