summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDave Hansen <dave.hansen@linux.intel.com>2017-07-07 00:36:44 +0200
committerLinus Torvalds <torvalds@linux-foundation.org>2017-07-07 01:24:31 +0200
commitc4e1be9ec1130fff4d691cdc0e0f9d666009f9ae (patch)
tree0def23a809ab189275b8f664e5fb2793593608e4 /drivers
parentmm: allow slab_nomerge to be set at build time (diff)
downloadlinux-c4e1be9ec1130fff4d691cdc0e0f9d666009f9ae.tar.xz
linux-c4e1be9ec1130fff4d691cdc0e0f9d666009f9ae.zip
mm, sparsemem: break out of loops early
There are a number of times that we loop over NR_MEM_SECTIONS, looking for section_present() on each section. But, when we have very large physical address spaces (large MAX_PHYSMEM_BITS), NR_MEM_SECTIONS becomes very large, making the loops quite long. With MAX_PHYSMEM_BITS=46 and a section size of 128MB, the current loops are 512k iterations, which we barely notice on modern hardware. But, raising MAX_PHYSMEM_BITS higher (like we will see on systems that support 5-level paging) makes this 64x longer and we start to notice, especially on slower systems like simulators. A 10-second delay for 512k iterations is annoying. But, a 640- second delay is crippling. This does not help if we have extremely sparse physical address spaces, but those are quite rare. We expect that most of the "slow" systems where this matters will also be quite small and non-sparse. To fix this, we track the highest section we've ever encountered. This lets us know when we will *never* see another section_present(), and lets us break out of the loops earlier. Doing the whole for_each_present_section_nr() macro is probably overkill, but it will ensure that any future loop iterations that we grow are more likely to be correct. Kirrill said "It shaved almost 40 seconds from boot time in qemu with 5-level paging enabled for me". Link: http://lkml.kernel.org/r/20170504174434.C45A4735@viggo.jf.intel.com Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com> Tested-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/base/memory.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index cc4f1d0cbffe..90225ffee501 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -820,6 +820,10 @@ int __init memory_dev_init(void)
*/
mutex_lock(&mem_sysfs_mutex);
for (i = 0; i < NR_MEM_SECTIONS; i += sections_per_block) {
+ /* Don't iterate over sections we know are !present: */
+ if (i > __highest_present_section_nr)
+ break;
+
err = add_memory_block(i);
if (!ret)
ret = err;