aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorMel Gorman <mgorman@suse.de>2014-08-06 19:07:14 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-08-06 21:01:20 -0400
commit3484b2de9499df23c4604a513b36f96326ae81ad (patch)
treefbaaed00603474887953459b01e09c5b9ff7379f /mm
parent24b7e5819ad5cbef2b7c7376510862aa8319d240 (diff)
mm: rearrange zone fields into read-only, page alloc, statistics and page reclaim lines
The arrangement of struct zone has changed over time and now it has reached the point where there is some inappropriate sharing going on. On x86-64 for example o The zone->node field is shared with the zone lock and zone->node is accessed frequently from the page allocator due to the fair zone allocation policy. o span_seqlock is almost never used by shares a line with free_area o Some zone statistics share a cache line with the LRU lock so reclaim-intensive and allocator-intensive workloads can bounce the cache line on a stat update This patch rearranges struct zone to put read-only and read-mostly fields together and then splits the page allocator intensive fields, the zone statistics and the page reclaim intensive fields into their own cache lines. Note that the type of lowmem_reserve changes due to the watermark calculations being signed and avoiding a signed/unsigned conversion there. On the test configuration I used the overall size of struct zone shrunk by one cache line. On smaller machines, this is not likely to be noticable. However, on a 4-node NUMA machine running tiobench the system CPU overhead is reduced by this patch. 3.16.0-rc3 3.16.0-rc3 vanillarearrange-v5r9 User 746.94 759.78 System 65336.22 58350.98 Elapsed 27553.52 27282.02 Signed-off-by: Mel Gorman <mgorman@suse.de> Acked-by: Johannes Weiner <hannes@cmpxchg.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm')
-rw-r--r--mm/page_alloc.c7
-rw-r--r--mm/vmstat.c4
2 files changed, 5 insertions, 6 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 0987ac9f0a4e..b7381d11f021 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -1708,7 +1708,6 @@ static bool __zone_watermark_ok(struct zone *z, unsigned int order,
1708{ 1708{
1709 /* free_pages my go negative - that's OK */ 1709 /* free_pages my go negative - that's OK */
1710 long min = mark; 1710 long min = mark;
1711 long lowmem_reserve = z->lowmem_reserve[classzone_idx];
1712 int o; 1711 int o;
1713 long free_cma = 0; 1712 long free_cma = 0;
1714 1713
@@ -1723,7 +1722,7 @@ static bool __zone_watermark_ok(struct zone *z, unsigned int order,
1723 free_cma = zone_page_state(z, NR_FREE_CMA_PAGES); 1722 free_cma = zone_page_state(z, NR_FREE_CMA_PAGES);
1724#endif 1723#endif
1725 1724
1726 if (free_pages - free_cma <= min + lowmem_reserve) 1725 if (free_pages - free_cma <= min + z->lowmem_reserve[classzone_idx])
1727 return false; 1726 return false;
1728 for (o = 0; o < order; o++) { 1727 for (o = 0; o < order; o++) {
1729 /* At the next order, this order's pages become unavailable */ 1728 /* At the next order, this order's pages become unavailable */
@@ -3254,7 +3253,7 @@ void show_free_areas(unsigned int filter)
3254 ); 3253 );
3255 printk("lowmem_reserve[]:"); 3254 printk("lowmem_reserve[]:");
3256 for (i = 0; i < MAX_NR_ZONES; i++) 3255 for (i = 0; i < MAX_NR_ZONES; i++)
3257 printk(" %lu", zone->lowmem_reserve[i]); 3256 printk(" %ld", zone->lowmem_reserve[i]);
3258 printk("\n"); 3257 printk("\n");
3259 } 3258 }
3260 3259
@@ -5575,7 +5574,7 @@ static void calculate_totalreserve_pages(void)
5575 for_each_online_pgdat(pgdat) { 5574 for_each_online_pgdat(pgdat) {
5576 for (i = 0; i < MAX_NR_ZONES; i++) { 5575 for (i = 0; i < MAX_NR_ZONES; i++) {
5577 struct zone *zone = pgdat->node_zones + i; 5576 struct zone *zone = pgdat->node_zones + i;
5578 unsigned long max = 0; 5577 long max = 0;
5579 5578
5580 /* Find valid and maximum lowmem_reserve in the zone */ 5579 /* Find valid and maximum lowmem_reserve in the zone */
5581 for (j = i; j < MAX_NR_ZONES; j++) { 5580 for (j = i; j < MAX_NR_ZONES; j++) {
diff --git a/mm/vmstat.c b/mm/vmstat.c
index b37bd49bfd55..8267f77d1875 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -1077,10 +1077,10 @@ static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat,
1077 zone_page_state(zone, i)); 1077 zone_page_state(zone, i));
1078 1078
1079 seq_printf(m, 1079 seq_printf(m,
1080 "\n protection: (%lu", 1080 "\n protection: (%ld",
1081 zone->lowmem_reserve[0]); 1081 zone->lowmem_reserve[0]);
1082 for (i = 1; i < ARRAY_SIZE(zone->lowmem_reserve); i++) 1082 for (i = 1; i < ARRAY_SIZE(zone->lowmem_reserve); i++)
1083 seq_printf(m, ", %lu", zone->lowmem_reserve[i]); 1083 seq_printf(m, ", %ld", zone->lowmem_reserve[i]);
1084 seq_printf(m, 1084 seq_printf(m,
1085 ")" 1085 ")"
1086 "\n pagesets"); 1086 "\n pagesets");