The "kmem -i" command is extremely slow (appears to hang) on dumps from large memory systems. For example, on 120GB crash dump from a high-end server with 32TB of RAM (ie. 8Giga Pages), the "kmem -i" command is taking over 50 minutes to execute on a DL380 Gen10. To report basic general memory usage figures, we should only be reading global counters, without having to walk the full flat/sparse mem map page table. Hence, dump_kmeminfo() should first be reading globals, and then only call dump_mem_map() if important information (ie. slabs or total ram) is missing. Signed-off-by: Georges Aureau <georges.aureau@xxxxxxx> -- diff --git a/memory.c b/memory.c index 8c01ed0..eb4574c 100644 --- a/memory.c +++ b/memory.c @@ -8546,18 +8546,23 @@ dump_kmeminfo(void) ulong get_buffers; ulong get_slabs; char buf[BUFSIZE]; + ulong flags; - - BZERO(&meminfo, sizeof(struct meminfo)); - meminfo.flags = GET_ALL; - dump_mem_map(&meminfo); - get_totalram = meminfo.get_totalram; - shared_pages = meminfo.get_shared; - get_buffers = meminfo.get_buffers; - get_slabs = meminfo.get_slabs; + /* + * By default, we will no longer call dump_mem_map() as this is too + * slow for large memory systems. If we have to call it (eg. missing + * important information such as slabs or total ram), we will also + * collect shared pages. Otherwise, we won't print shared pages. + * Shared page + */ + flags = GET_SHARED_PAGES; + shared_pages = 0; + get_totalram = 0; + get_buffers = 0; + get_slabs = 0; /* - * If vm_stat array exists, override page search info. + * If vm_stat array does not exists, then set mem map flag. */ if (vm_stat_init()) { if (dump_vm_stat("NR_SLAB", &nr_slab, 0)) @@ -8572,9 +8577,10 @@ dump_kmeminfo(void) if (dump_vm_stat("NR_SLAB_UNRECLAIMABLE_B", &nr_slab, 0)) get_slabs += nr_slab; } + } else { + flags |= GET_SLAB_PAGES; } - fprintf(fp, "%s", kmeminfo_hdr); /* * Get total RAM based upon how the various versions of si_meminfo() * have done it, latest to earliest: @@ -8586,9 +8592,32 @@ dump_kmeminfo(void) symbol_exists("_totalram_pages")) { totalram_pages = vt->totalram_pages ? vt->totalram_pages : get_totalram; - } else - totalram_pages = get_totalram; + } else { + flags |= GET_TOTALRAM_PAGES; + } + /* + * If we want more than just shared pages (missing slabs or total ram) + * then call dump_mem_map() and also collect buffers. + */ + if (flags != GET_SHARED_PAGES) { + BZERO(&meminfo, sizeof(struct meminfo)); + flags |= GET_BUFFERS_PAGES; + meminfo.flags = flags; + dump_mem_map(&meminfo); + /* Update the missing information */ + if (flags & GET_SLAB_PAGES) { + get_slabs = meminfo.get_slabs; + } + if (flags & GET_TOTALRAM_PAGES) { + get_totalram = meminfo.get_totalram; + totalram_pages = get_totalram; + } + shared_pages = meminfo.get_shared; + get_buffers = meminfo.get_buffers; + } + + fprintf(fp, "%s", kmeminfo_hdr); fprintf(fp, "%13s %7ld %11s ----\n", "TOTAL MEM", totalram_pages, pages_to_size(totalram_pages, buf)); @@ -8613,9 +8642,11 @@ dump_kmeminfo(void) * differently than the kernel -- it just tallies the non-reserved * pages that have a count of greater than 1. */ - pct = (shared_pages * 100)/totalram_pages; - fprintf(fp, "%13s %7ld %11s %3ld%% of TOTAL MEM\n", - "SHARED", shared_pages, pages_to_size(shared_pages, buf), pct); + if (shared_pages) { + pct = (shared_pages * 100)/totalram_pages; + fprintf(fp, "%13s %7ld %11s %3ld%% of TOTAL MEM\n", + "SHARED", shared_pages, pages_to_size(shared_pages, buf), pct); + } subtract_buffer_pages = 0; if (symbol_exists("buffermem_pages")) { @@ -8634,7 +8665,7 @@ dump_kmeminfo(void) fprintf(fp, "%13s %7ld %11s %3ld%% of TOTAL MEM\n", "BUFFERS", buffer_pages, pages_to_size(buffer_pages, buf), pct); - if (CRASHDEBUG(1)) + if (CRASHDEBUG(1)&&(flags&GET_BUFFERS_PAGES)) error(NOTE, "pages with buffers: %ld\n", get_buffers); /* -- Crash-utility mailing list -- devel@xxxxxxxxxxxxxxxxxxxxxxxxxxx To unsubscribe send an email to devel-leave@xxxxxxxxxxxxxxxxxxxxxxxxxxx https://${domain_name}/admin/lists/devel.lists.crash-utility.osci.io/ Contribution Guidelines: https://github.com/crash-utility/crash/wiki