mm: compaction: add a tunable that decides when memory should be compacted and when...
authorMel Gorman <mel@csn.ul.ie>
Mon, 24 May 2010 21:32:31 +0000 (14:32 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 25 May 2010 15:06:59 +0000 (08:06 -0700)
The kernel applies some heuristics when deciding if memory should be
compacted or reclaimed to satisfy a high-order allocation.  One of these
is based on the fragmentation.  If the index is below 500, memory will not
be compacted.  This choice is arbitrary and not based on data.  To help
optimise the system and set a sensible default for this value, this patch
adds a sysctl extfrag_threshold.  The kernel will only compact memory if
the fragmentation index is above the extfrag_threshold.

[randy.dunlap@oracle.com: Fix build errors when proc fs is not configured]
Signed-off-by: Mel Gorman <mel@csn.ul.ie>
Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com>
Cc: Rik van Riel <riel@redhat.com>
Cc: Minchan Kim <minchan.kim@gmail.com>
Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Cc: Christoph Lameter <cl@linux-foundation.org>
Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Documentation/sysctl/vm.txt
include/linux/compaction.h
kernel/sysctl.c
mm/compaction.c

index 56dd29b97a91b2283b15d3438f0da3a151e228ed..5fdbb612aeb840af5c5eec80103c660be3da6c06 100644 (file)
@@ -27,6 +27,7 @@ Currently, these files are in /proc/sys/vm:
 - dirty_ratio
 - dirty_writeback_centisecs
 - drop_caches
+- extfrag_threshold
 - hugepages_treat_as_movable
 - hugetlb_shm_group
 - laptop_mode
@@ -149,6 +150,20 @@ user should run `sync' first.
 
 ==============================================================
 
+extfrag_threshold
+
+This parameter affects whether the kernel will compact memory or direct
+reclaim to satisfy a high-order allocation. /proc/extfrag_index shows what
+the fragmentation index for each order is in each zone in the system. Values
+tending towards 0 imply allocations would fail due to lack of memory,
+values towards 1000 imply failures are due to fragmentation and -1 implies
+that the allocation will succeed as long as watermarks are met.
+
+The kernel will not compact memory in a zone if the
+fragmentation index is <= extfrag_threshold. The default value is 500.
+
+==============================================================
+
 hugepages_treat_as_movable
 
 This parameter is only useful when kernelcore= is specified at boot time to
index eed40ec4280b2275e210ca848674df99174528b5..3719325c6091faff1a17b97c0b966f72273422f1 100644 (file)
@@ -15,6 +15,9 @@
 extern int sysctl_compact_memory;
 extern int sysctl_compaction_handler(struct ctl_table *table, int write,
                        void __user *buffer, size_t *length, loff_t *ppos);
+extern int sysctl_extfrag_threshold;
+extern int sysctl_extfrag_handler(struct ctl_table *table, int write,
+                       void __user *buffer, size_t *length, loff_t *ppos);
 
 extern int fragmentation_index(struct zone *zone, unsigned int order);
 extern unsigned long try_to_compact_pages(struct zonelist *zonelist,
index 284f330d6a018c3bc1327408d83a367ea2556080..84ff5e75c084f2d4ccbe94fd6ce0a43061726125 100644 (file)
@@ -263,6 +263,11 @@ static int min_sched_shares_ratelimit = 100000; /* 100 usec */
 static int max_sched_shares_ratelimit = NSEC_PER_SEC; /* 1 second */
 #endif
 
+#ifdef CONFIG_COMPACTION
+static int min_extfrag_threshold;
+static int max_extfrag_threshold = 1000;
+#endif
+
 static struct ctl_table kern_table[] = {
        {
                .procname       = "sched_child_runs_first",
@@ -1130,6 +1135,16 @@ static struct ctl_table vm_table[] = {
                .mode           = 0200,
                .proc_handler   = sysctl_compaction_handler,
        },
+       {
+               .procname       = "extfrag_threshold",
+               .data           = &sysctl_extfrag_threshold,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = sysctl_extfrag_handler,
+               .extra1         = &min_extfrag_threshold,
+               .extra2         = &max_extfrag_threshold,
+       },
+
 #endif /* CONFIG_COMPACTION */
        {
                .procname       = "min_free_kbytes",
index 9583e193dc47b3e0f5728629bec48a94685de037..94cce51b0b3535af75c20f29ecb86a11aba32a71 100644 (file)
@@ -433,6 +433,8 @@ static unsigned long compact_zone_order(struct zone *zone,
        return compact_zone(zone, &cc);
 }
 
+int sysctl_extfrag_threshold = 500;
+
 /**
  * try_to_compact_pages - Direct compact to satisfy a high-order allocation
  * @zonelist: The zonelist used for the current allocation
@@ -491,7 +493,7 @@ unsigned long try_to_compact_pages(struct zonelist *zonelist,
                 * Only compact if a failure would be due to fragmentation.
                 */
                fragindex = fragmentation_index(zone, order);
-               if (fragindex >= 0 && fragindex <= 500)
+               if (fragindex >= 0 && fragindex <= sysctl_extfrag_threshold)
                        continue;
 
                if (fragindex == -1 && zone_watermark_ok(zone, order, watermark, 0, 0)) {
@@ -572,6 +574,14 @@ int sysctl_compaction_handler(struct ctl_table *table, int write,
        return 0;
 }
 
+int sysctl_extfrag_handler(struct ctl_table *table, int write,
+                       void __user *buffer, size_t *length, loff_t *ppos)
+{
+       proc_dointvec_minmax(table, write, buffer, length, ppos);
+
+       return 0;
+}
+
 #if defined(CONFIG_SYSFS) && defined(CONFIG_NUMA)
 ssize_t sysfs_compact_node(struct sys_device *dev,
                        struct sysdev_attribute *attr,