summaryrefslogtreecommitdiffstats
path: root/mm/compaction.c
diff options
context:
space:
mode:
authorMel Gorman <mgorman@techsingularity.net>2019-03-05 18:45:34 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2019-03-06 00:07:17 -0500
commit4fca9730c51d51f643f2a3f8f10ebd718349c80f (patch)
treec17ec7221a82a25ea6a99ebe6e6ed15f3202f38b /mm/compaction.c
parentdbe2d4e4f12e07c6a2215e3603a5f77056323081 (diff)
mm, compaction: sample pageblocks for free pages
Once fast searching finishes, there is a possibility that the linear scanner is scanning full blocks found by the fast scanner earlier. This patch uses an adaptive stride to sample pageblocks for free pages. The more consecutive full pageblocks encountered, the larger the stride until a pageblock with free pages is found. The scanners might meet slightly sooner but it is an acceptable risk given that the search of the free lists may still encounter the pages and adjust the cached PFN of the free scanner accordingly. 5.0.0-rc1 5.0.0-rc1 roundrobin-v3r17 samplefree-v3r17 Amean fault-both-1 0.00 ( 0.00%) 0.00 * 0.00%* Amean fault-both-3 2752.37 ( 0.00%) 2729.95 ( 0.81%) Amean fault-both-5 4341.69 ( 0.00%) 4397.80 ( -1.29%) Amean fault-both-7 6308.75 ( 0.00%) 6097.61 ( 3.35%) Amean fault-both-12 10241.81 ( 0.00%) 9407.15 ( 8.15%) Amean fault-both-18 13736.09 ( 0.00%) 10857.63 * 20.96%* Amean fault-both-24 16853.95 ( 0.00%) 13323.24 * 20.95%* Amean fault-both-30 15862.61 ( 0.00%) 17345.44 ( -9.35%) Amean fault-both-32 18450.85 ( 0.00%) 16892.00 ( 8.45%) The latency is mildly improved offseting some overhead from earlier patches that are prerequisites for the rest of the series. However, a major impact is on the free scan rate with an 82% reduction. 5.0.0-rc1 5.0.0-rc1 roundrobin-v3r17 samplefree-v3r17 Compaction migrate scanned 21607271 20116887 Compaction free scanned 95336406 16668703 It's also the first time in the series where the number of pages scanned by the migration scanner is greater than the free scanner due to the increased search efficiency. Link: http://lkml.kernel.org/r/20190118175136.31341-21-mgorman@techsingularity.net Signed-off-by: Mel Gorman <mgorman@techsingularity.net> Acked-by: Vlastimil Babka <vbabka@suse.cz> Cc: Andrea Arcangeli <aarcange@redhat.com> Cc: Dan Carpenter <dan.carpenter@oracle.com> Cc: David Rientjes <rientjes@google.com> Cc: YueHaibing <yuehaibing@huawei.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/compaction.c')
-rw-r--r--mm/compaction.c28
1 files changed, 22 insertions, 6 deletions
diff --git a/mm/compaction.c b/mm/compaction.c
index b3055983a80f..b83cdb42f249 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -440,6 +440,7 @@ static unsigned long isolate_freepages_block(struct compact_control *cc,
440 unsigned long *start_pfn, 440 unsigned long *start_pfn,
441 unsigned long end_pfn, 441 unsigned long end_pfn,
442 struct list_head *freelist, 442 struct list_head *freelist,
443 unsigned int stride,
443 bool strict) 444 bool strict)
444{ 445{
445 int nr_scanned = 0, total_isolated = 0; 446 int nr_scanned = 0, total_isolated = 0;
@@ -449,10 +450,14 @@ static unsigned long isolate_freepages_block(struct compact_control *cc,
449 unsigned long blockpfn = *start_pfn; 450 unsigned long blockpfn = *start_pfn;
450 unsigned int order; 451 unsigned int order;
451 452
453 /* Strict mode is for isolation, speed is secondary */
454 if (strict)
455 stride = 1;
456
452 cursor = pfn_to_page(blockpfn); 457 cursor = pfn_to_page(blockpfn);
453 458
454 /* Isolate free pages. */ 459 /* Isolate free pages. */
455 for (; blockpfn < end_pfn; blockpfn++, cursor++) { 460 for (; blockpfn < end_pfn; blockpfn += stride, cursor += stride) {
456 int isolated; 461 int isolated;
457 struct page *page = cursor; 462 struct page *page = cursor;
458 463
@@ -614,7 +619,7 @@ isolate_freepages_range(struct compact_control *cc,
614 break; 619 break;
615 620
616 isolated = isolate_freepages_block(cc, &isolate_start_pfn, 621 isolated = isolate_freepages_block(cc, &isolate_start_pfn,
617 block_end_pfn, &freelist, true); 622 block_end_pfn, &freelist, 0, true);
618 623
619 /* 624 /*
620 * In strict mode, isolate_freepages_block() returns 0 if 625 * In strict mode, isolate_freepages_block() returns 0 if
@@ -1132,7 +1137,7 @@ fast_isolate_around(struct compact_control *cc, unsigned long pfn, unsigned long
1132 1137
1133 /* Scan before */ 1138 /* Scan before */
1134 if (start_pfn != pfn) { 1139 if (start_pfn != pfn) {
1135 isolate_freepages_block(cc, &start_pfn, pfn, &cc->freepages, false); 1140 isolate_freepages_block(cc, &start_pfn, pfn, &cc->freepages, 1, false);
1136 if (cc->nr_freepages >= cc->nr_migratepages) 1141 if (cc->nr_freepages >= cc->nr_migratepages)
1137 return; 1142 return;
1138 } 1143 }
@@ -1140,7 +1145,7 @@ fast_isolate_around(struct compact_control *cc, unsigned long pfn, unsigned long
1140 /* Scan after */ 1145 /* Scan after */
1141 start_pfn = pfn + nr_isolated; 1146 start_pfn = pfn + nr_isolated;
1142 if (start_pfn != end_pfn) 1147 if (start_pfn != end_pfn)
1143 isolate_freepages_block(cc, &start_pfn, end_pfn, &cc->freepages, false); 1148 isolate_freepages_block(cc, &start_pfn, end_pfn, &cc->freepages, 1, false);
1144 1149
1145 /* Skip this pageblock in the future as it's full or nearly full */ 1150 /* Skip this pageblock in the future as it's full or nearly full */
1146 if (cc->nr_freepages < cc->nr_migratepages) 1151 if (cc->nr_freepages < cc->nr_migratepages)
@@ -1332,6 +1337,7 @@ static void isolate_freepages(struct compact_control *cc)
1332 unsigned long block_end_pfn; /* end of current pageblock */ 1337 unsigned long block_end_pfn; /* end of current pageblock */
1333 unsigned long low_pfn; /* lowest pfn scanner is able to scan */ 1338 unsigned long low_pfn; /* lowest pfn scanner is able to scan */
1334 struct list_head *freelist = &cc->freepages; 1339 struct list_head *freelist = &cc->freepages;
1340 unsigned int stride;
1335 1341
1336 /* Try a small search of the free lists for a candidate */ 1342 /* Try a small search of the free lists for a candidate */
1337 isolate_start_pfn = fast_isolate_freepages(cc); 1343 isolate_start_pfn = fast_isolate_freepages(cc);
@@ -1354,6 +1360,7 @@ static void isolate_freepages(struct compact_control *cc)
1354 block_end_pfn = min(block_start_pfn + pageblock_nr_pages, 1360 block_end_pfn = min(block_start_pfn + pageblock_nr_pages,
1355 zone_end_pfn(zone)); 1361 zone_end_pfn(zone));
1356 low_pfn = pageblock_end_pfn(cc->migrate_pfn); 1362 low_pfn = pageblock_end_pfn(cc->migrate_pfn);
1363 stride = cc->mode == MIGRATE_ASYNC ? COMPACT_CLUSTER_MAX : 1;
1357 1364
1358 /* 1365 /*
1359 * Isolate free pages until enough are available to migrate the 1366 * Isolate free pages until enough are available to migrate the
@@ -1364,6 +1371,8 @@ static void isolate_freepages(struct compact_control *cc)
1364 block_end_pfn = block_start_pfn, 1371 block_end_pfn = block_start_pfn,
1365 block_start_pfn -= pageblock_nr_pages, 1372 block_start_pfn -= pageblock_nr_pages,
1366 isolate_start_pfn = block_start_pfn) { 1373 isolate_start_pfn = block_start_pfn) {
1374 unsigned long nr_isolated;
1375
1367 /* 1376 /*
1368 * This can iterate a massively long zone without finding any 1377 * This can iterate a massively long zone without finding any
1369 * suitable migration targets, so periodically check resched. 1378 * suitable migration targets, so periodically check resched.
@@ -1385,8 +1394,8 @@ static void isolate_freepages(struct compact_control *cc)
1385 continue; 1394 continue;
1386 1395
1387 /* Found a block suitable for isolating free pages from. */ 1396 /* Found a block suitable for isolating free pages from. */
1388 isolate_freepages_block(cc, &isolate_start_pfn, block_end_pfn, 1397 nr_isolated = isolate_freepages_block(cc, &isolate_start_pfn,
1389 freelist, false); 1398 block_end_pfn, freelist, stride, false);
1390 1399
1391 /* Update the skip hint if the full pageblock was scanned */ 1400 /* Update the skip hint if the full pageblock was scanned */
1392 if (isolate_start_pfn == block_end_pfn) 1401 if (isolate_start_pfn == block_end_pfn)
@@ -1410,6 +1419,13 @@ static void isolate_freepages(struct compact_control *cc)
1410 */ 1419 */
1411 break; 1420 break;
1412 } 1421 }
1422
1423 /* Adjust stride depending on isolation */
1424 if (nr_isolated) {
1425 stride = 1;
1426 continue;
1427 }
1428 stride = min_t(unsigned int, COMPACT_CLUSTER_MAX, stride << 1);
1413 } 1429 }
1414 1430
1415 /* 1431 /*