Skip to content

Commit 2fe0341

Browse files
Peng Zhangrppt
authored andcommitted
memblock: Avoid useless checks in memblock_merge_regions().
memblock_merge_regions() is called after regions have been modified to merge the neighboring compatible regions. That will check all regions but most checks are useless. Most of the time we only insert one or a few new regions, or modify one or a few regions. At this time, we don't need to check all the regions. We only need to check the changed regions, because other not related regions cannot be merged. Add two parameters to memblock_merge_regions() to indicate the lower and upper boundary to scan. Debug code that counts the number of total iterations in memblock_merge_regions(), like for instance void memblock_merge_regions(struct memblock_type *type) { static int iteration_count = 0; static int max_nr_regions = 0; max_nr_regions = max(max_nr_regions, (int)type->cnt); ... while () { iteration_count++; ... } pr_info("iteration_count: %d max_nr_regions %d", iteration_count, max_nr_regions); } Produces the following numbers on a physical machine with 1T of memory: before: [2.472243] iteration_count: 45410 max_nr_regions 178 after: [2.470869] iteration_count: 923 max_nr_regions 176 The actual startup speed seems to change little, but it does reduce the scan overhead. Signed-off-by: Peng Zhang <[email protected]> Link: https://lore.kernel.org/r/[email protected] [rppt: massaged the changelog] Signed-off-by: Mike Rapoport (IBM) <[email protected]>
1 parent ad500fb commit 2fe0341

File tree

1 file changed

+25
-12
lines changed

1 file changed

+25
-12
lines changed

mm/memblock.c

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -500,15 +500,19 @@ static int __init_memblock memblock_double_array(struct memblock_type *type,
500500
/**
501501
* memblock_merge_regions - merge neighboring compatible regions
502502
* @type: memblock type to scan
503-
*
504-
* Scan @type and merge neighboring compatible regions.
503+
* @start_rgn: start scanning from (@start_rgn - 1)
504+
* @end_rgn: end scanning at (@end_rgn - 1)
505+
* Scan @type and merge neighboring compatible regions in [@start_rgn - 1, @end_rgn)
505506
*/
506-
static void __init_memblock memblock_merge_regions(struct memblock_type *type)
507+
static void __init_memblock memblock_merge_regions(struct memblock_type *type,
508+
unsigned long start_rgn,
509+
unsigned long end_rgn)
507510
{
508511
int i = 0;
509-
510-
/* cnt never goes below 1 */
511-
while (i < type->cnt - 1) {
512+
if (start_rgn)
513+
i = start_rgn - 1;
514+
end_rgn = min(end_rgn, type->cnt - 1);
515+
while (i < end_rgn) {
512516
struct memblock_region *this = &type->regions[i];
513517
struct memblock_region *next = &type->regions[i + 1];
514518

@@ -525,6 +529,7 @@ static void __init_memblock memblock_merge_regions(struct memblock_type *type)
525529
/* move forward from next + 1, index of which is i + 2 */
526530
memmove(next, next + 1, (type->cnt - (i + 2)) * sizeof(*next));
527531
type->cnt--;
532+
end_rgn--;
528533
}
529534
}
530535

@@ -581,7 +586,7 @@ static int __init_memblock memblock_add_range(struct memblock_type *type,
581586
bool insert = false;
582587
phys_addr_t obase = base;
583588
phys_addr_t end = base + memblock_cap_size(base, &size);
584-
int idx, nr_new;
589+
int idx, nr_new, start_rgn = -1, end_rgn;
585590
struct memblock_region *rgn;
586591

587592
if (!size)
@@ -635,10 +640,14 @@ static int __init_memblock memblock_add_range(struct memblock_type *type,
635640
#endif
636641
WARN_ON(flags != rgn->flags);
637642
nr_new++;
638-
if (insert)
643+
if (insert) {
644+
if (start_rgn == -1)
645+
start_rgn = idx;
646+
end_rgn = idx + 1;
639647
memblock_insert_region(type, idx++, base,
640648
rbase - base, nid,
641649
flags);
650+
}
642651
}
643652
/* area below @rend is dealt with, forget about it */
644653
base = min(rend, end);
@@ -647,9 +656,13 @@ static int __init_memblock memblock_add_range(struct memblock_type *type,
647656
/* insert the remaining portion */
648657
if (base < end) {
649658
nr_new++;
650-
if (insert)
659+
if (insert) {
660+
if (start_rgn == -1)
661+
start_rgn = idx;
662+
end_rgn = idx + 1;
651663
memblock_insert_region(type, idx, base, end - base,
652664
nid, flags);
665+
}
653666
}
654667

655668
if (!nr_new)
@@ -666,7 +679,7 @@ static int __init_memblock memblock_add_range(struct memblock_type *type,
666679
insert = true;
667680
goto repeat;
668681
} else {
669-
memblock_merge_regions(type);
682+
memblock_merge_regions(type, start_rgn, end_rgn);
670683
return 0;
671684
}
672685
}
@@ -902,7 +915,7 @@ static int __init_memblock memblock_setclr_flag(phys_addr_t base,
902915
r->flags &= ~flag;
903916
}
904917

905-
memblock_merge_regions(type);
918+
memblock_merge_regions(type, start_rgn, end_rgn);
906919
return 0;
907920
}
908921

@@ -1275,7 +1288,7 @@ int __init_memblock memblock_set_node(phys_addr_t base, phys_addr_t size,
12751288
for (i = start_rgn; i < end_rgn; i++)
12761289
memblock_set_region_node(&type->regions[i], nid);
12771290

1278-
memblock_merge_regions(type);
1291+
memblock_merge_regions(type, start_rgn, end_rgn);
12791292
#endif
12801293
return 0;
12811294
}

0 commit comments

Comments
 (0)