Commit 3395ee0588795b0b3bd889c260e55959cf2b61f5

Authored by Paul Menage
Committed by Linus Torvalds
1 parent 8f5be20bf8

[PATCH] mm: add noaliencache boot option to disable numa alien caches

When using numa=fake on non-NUMA hardware there is no benefit to having the
alien caches, and they consume much memory.

Add a kernel boot option to disable them.

Christoph sayeth "This is good to have even on large NUMA.  The problem is
that the alien caches grow by the square of the size of the system in terms of
nodes."

Cc: Christoph Lameter <clameter@engr.sgi.com>
Cc: Pekka Enberg <penberg@cs.helsinki.fi>
Cc: Manfred Spraul <manfred@colorfullife.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

Showing 2 changed files with 33 additions and 9 deletions Side-by-side Diff

Documentation/kernel-parameters.txt
... ... @@ -1012,6 +1012,10 @@
1012 1012 emulation library even if a 387 maths coprocessor
1013 1013 is present.
1014 1014  
  1015 + noaliencache [MM, NUMA] Disables the allcoation of alien caches in
  1016 + the slab allocator. Saves per-node memory, but will
  1017 + impact performance on real NUMA hardware.
  1018 +
1015 1019 noalign [KNL,ARM]
1016 1020  
1017 1021 noapic [SMP,APIC] Tells the kernel to not make use of any
... ... @@ -869,6 +869,22 @@
869 869 dump_stack();
870 870 }
871 871  
  872 +/*
  873 + * By default on NUMA we use alien caches to stage the freeing of
  874 + * objects allocated from other nodes. This causes massive memory
  875 + * inefficiencies when using fake NUMA setup to split memory into a
  876 + * large number of small nodes, so it can be disabled on the command
  877 + * line
  878 + */
  879 +
  880 +static int use_alien_caches __read_mostly = 1;
  881 +static int __init noaliencache_setup(char *s)
  882 +{
  883 + use_alien_caches = 0;
  884 + return 1;
  885 +}
  886 +__setup("noaliencache", noaliencache_setup);
  887 +
872 888 #ifdef CONFIG_NUMA
873 889 /*
874 890 * Special reaping functions for NUMA systems called from cache_reap().
... ... @@ -1117,7 +1133,7 @@
1117 1133 * Make sure we are not freeing a object from another node to the array
1118 1134 * cache on this cpu.
1119 1135 */
1120   - if (likely(slabp->nodeid == node))
  1136 + if (likely(slabp->nodeid == node) || unlikely(!use_alien_caches))
1121 1137 return 0;
1122 1138  
1123 1139 l3 = cachep->nodelists[node];
... ... @@ -1195,7 +1211,7 @@
1195 1211 list_for_each_entry(cachep, &cache_chain, next) {
1196 1212 struct array_cache *nc;
1197 1213 struct array_cache *shared;
1198   - struct array_cache **alien;
  1214 + struct array_cache **alien = NULL;
1199 1215  
1200 1216 nc = alloc_arraycache(node, cachep->limit,
1201 1217 cachep->batchcount);
... ... @@ -1207,9 +1223,11 @@
1207 1223 if (!shared)
1208 1224 goto bad;
1209 1225  
1210   - alien = alloc_alien_cache(node, cachep->limit);
1211   - if (!alien)
1212   - goto bad;
  1226 + if (use_alien_caches) {
  1227 + alien = alloc_alien_cache(node, cachep->limit);
  1228 + if (!alien)
  1229 + goto bad;
  1230 + }
1213 1231 cachep->array[cpu] = nc;
1214 1232 l3 = cachep->nodelists[node];
1215 1233 BUG_ON(!l3);
1216 1234  
... ... @@ -3590,13 +3608,15 @@
3590 3608 int node;
3591 3609 struct kmem_list3 *l3;
3592 3610 struct array_cache *new_shared;
3593   - struct array_cache **new_alien;
  3611 + struct array_cache **new_alien = NULL;
3594 3612  
3595 3613 for_each_online_node(node) {
3596 3614  
3597   - new_alien = alloc_alien_cache(node, cachep->limit);
3598   - if (!new_alien)
3599   - goto fail;
  3615 + if (use_alien_caches) {
  3616 + new_alien = alloc_alien_cache(node, cachep->limit);
  3617 + if (!new_alien)
  3618 + goto fail;
  3619 + }
3600 3620  
3601 3621 new_shared = alloc_arraycache(node,
3602 3622 cachep->shared*cachep->batchcount,