ryncsn / memstrack

A memory allocation tracer combined with stack trace.
GNU General Public License v3.0
152 stars 17 forks source link

Empty module_summary and module_top report when using pageowner as backend #15

Open liutgnu opened 2 years ago

liutgnu commented 2 years ago

Hi kasong,

For memstrack cmdline:

$ ./memstrack --notui --backend pageowner --report module_summary,module_top,proc_slab_static or $ ./memstrack --notui --backend ftrace --report module_summary,module_top,proc_slab_static

and rmmod/modprobe ext4 in another terminal at the same time, I will get empty module_summary and format module_top as:

======== Report format module_summary: ======== ======== Report format module_summary END ========

======== Report format module_top: ======== ======== Report format module_top END ========

======== Report format proc_slab_static: ======== Top Slab Usage: inode_cache: 15.1 MB dentry: 6.4 MB xfs_inode: 5.9 MB ..... ======== Report format proc_slab_static END ========

However if I use perf as backend, I can see the stacktrace and module in module_summary and module_top as:

======== Report format module_summary: ======== Module kvm using 0.0MB (4 pages), peak allocation 0.0MB (4 pages) Module ext4 using 0.0MB (2 pages), peak allocation 0.0MB (2 pages) ======== Report format module_summary END ========

======== Report format module_top: ======== Top stack usage of module kvm: (null) Pages: 4 (peak: 4) entry_SYSCALL_64_after_hwframe (0xffffffffaee0007c) Pages: 4 (peak: 4) do_syscall_64 (0xffffffffaec99ce9) Pages: 4 (peak: 4) .... ======== Report format module_top END ========

Then I made some debug, I found when pageowner and ftrace as backend, src/tracing.c:store_symbol_instead() will be called during init, which will set key_type = KEY_SYMBOL. Then in src/tracing:get_tracenode_module(), NULL will be return, so src/tracing:get_or_new_module() will not be called, neither did src/tracing:insert_hash_node(), and src/report.c:report_module_top() src/report.c:report_module_summary will report nothing because module_map.size=0.

char* get_tracenode_module(struct Tracenode *node) {
    if (!node->key)
        return NULL;

    if (key_type == KEY_SYMBOL)
        // TODO   <<----- 
        return NULL;
    else
        return kaddr_to_module(node->addr);
}

My question is, for pageowner as backend, why set key_type = KEY_SYMBOL during init, since there is //TODO commented, seems the function is not fully implemented though... In this case, are empty module_summary and module_top working as expected?

Thanks!

ryncsn commented 2 years ago

Hi Tao,

Thanks for reaching out about the problem.

When using perf as backend, memstrack can get the exact callsite address of each layer of stack trace, so by looking at the symbol addresses in /proc/kallsyms, memstrack can tell the symbol name of a callsite and which module a callsite come from.

When using ftrace/page_owner, currently memtrack directly record the resolved symbol name of each callsite, as ftrace/page_owner prints the symbols instead of the address. I tried to implement symbol name based look up here: https://github.com/ryncsn/memstrack/commit/a17589b5504645bf5fffff447f765b751fc9ff84

But it didn't work as expected, I haven't got time to look into it further yet, but it seems if two symbols in two different modules have the same name, we can't get the right module then... Maybe a better solution is to make ftrace/page_owner print the address/module name.

I'll try again to fix this later...

liutgnu commented 2 years ago

Hi kasong,

Thanks a lot for the info, now I understood the code better. I will give it a try as well when I have time.

Thanks, Tao Liu