On Thu, Jan 9, 2025 at 6:41 AM <devel-requ...@lists.crash-utility.osci.io> wrote:
> Date: Thu, 9 Jan 2025 11:39:18 +1300 > From: Tao Liu <l...@redhat.com> > Subject: [Crash-utility] Re: [PATCH v3] "kmem -i" extremely slow on > dumps from large memory systems > To: "Aureau, Georges (Kernel Tools ERT)" <georges.aur...@hpe.com> > Cc: "devel@lists.crash-utility.osci.io" > <devel@lists.crash-utility.osci.io> > Message-ID: > < > cao7dbbulic-3s+1a5o8nzt7pqaaos_ocfjqew6wwr8msv0l...@mail.gmail.com> > Content-Type: text/plain; charset="UTF-8" > > Hi Aureau, > > Thanks for the improvements. LGTM, so ack. > Applied(with minor changes): https://github.com/crash-utility/crash/commit/b39f8b558f9c71f91ae5f623a06b8db66291fbc8 Thanks Lianbo > > Thanks, > Tao Liu > > On Thu, Jan 9, 2025 at 3:38 AM Aureau, Georges (Kernel Tools ERT) > <georges.aur...@hpe.com> wrote: > > > > 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.aur...@hpe.com> > > -- > > help.c | 4 +++- > > memory.c | 72 > +++++++++++++++++++++++++++++++++++++++++++++++----------------- > > 2 files changed, 56 insertions(+), 20 deletions(-) > > > > diff --git a/help.c b/help.c > > index 4c30047..8bd74ac 100644 > > --- a/help.c > > +++ b/help.c > > @@ -6825,7 +6825,9 @@ char *help_kmem[] = { > > " -F same as -f, but also dumps all pages linked to that > header.", > > " -c walks through the page_hash_table and verifies > page_cache_size.", > > " -C same as -c, but also dumps all pages in the > page_hash_table.", > > -" -i displays general memory usage information", > > +" -i displays general memory usage information.", > > +" Note: SHARED is no longer printed (too slow on large > memory systems)", > > +" unless specifying \"-i=shared\".", > > " -v displays the mapped virtual memory regions allocated by > vmalloc().", > > " -V displays the kernel vm_stat table if it exists, or in more > recent", > > " kernels, the vm_zone_stat, vm_node_stat and vm_numa_stat > tables,", > > diff --git a/memory.c b/memory.c > > index 8c01ed0..ea00ef1 100644 > > --- a/memory.c > > +++ b/memory.c > > @@ -237,7 +237,7 @@ static void dump_vmlist(struct meminfo *); > > static void dump_vmap_area(struct meminfo *); > > static int get_vmap_area_list_from_nodes(ulong **); > > static int dump_page_lists(struct meminfo *); > > -static void dump_kmeminfo(void); > > +static void dump_kmeminfo(struct meminfo *); > > static int page_to_phys(ulong, physaddr_t *); > > static void display_memory(ulonglong, long, ulong, int, void *); > > static char *show_opt_string(struct searchinfo *); > > @@ -5107,7 +5107,7 @@ cmd_kmem(void) > > BZERO(&value[0], sizeof(ulonglong)*MAXARGS); > > pc->curcmd_flags &= ~HEADER_PRINTED; > > > > - while ((c = getopt(argcnt, args, > "gI:sS::rFfm:pvczCinl:L:PVoh")) != EOF) { > > + while ((c = getopt(argcnt, args, > "gI:sS::rFfm:pvczCi::nl:L:PVoh")) != EOF) { > > switch(c) > > { > > case 'V': > > @@ -5124,6 +5124,9 @@ cmd_kmem(void) > > > > case 'i': > > iflag = 1; > > + if (optarg && strcmp(optarg, "=shared") == 0) { > > + meminfo.flags = GET_SHARED_PAGES; > > + } > > break; > > > > case 'h': > > @@ -5410,7 +5413,7 @@ cmd_kmem(void) > > } > > > > if (iflag == 1) > > - dump_kmeminfo(); > > + dump_kmeminfo(&meminfo); > > > > if (pflag == 1) > > dump_mem_map(&meminfo); > > @@ -8515,7 +8518,7 @@ bailout: > > char *kmeminfo_hdr = " PAGES TOTAL > PERCENTAGE\n"; > > > > static void > > -dump_kmeminfo(void) > > +dump_kmeminfo(struct meminfo *mi) > > { > > int i, len; > > ulong totalram_pages; > > @@ -8546,18 +8549,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 > unless > > + * the caller explicitly requested shared pages ("kmem > -i=shared"). > > + */ > > + flags = mi->flags; > > + 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 +8580,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 +8595,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; > > + totalram_pages = 0; > > + } > > > > + /* > > + * If the caller wants shared pages or if we are missing > important data > > + * (ie. slab or totalram) then go through the slow > dump_mem_map() path. > > + */ > > + if (flags) { > > + BZERO(&meminfo, sizeof(struct meminfo)); > > + meminfo.flags = GET_ALL; > > + 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 +8645,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 (flags & GET_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")) { >
-- Crash-utility mailing list -- devel@lists.crash-utility.osci.io To unsubscribe send an email to devel-le...@lists.crash-utility.osci.io https://${domain_name}/admin/lists/devel.lists.crash-utility.osci.io/ Contribution Guidelines: https://github.com/crash-utility/crash/wiki