Note: This bug is displayed in read-only format because the product is no longer active in Red Hat Bugzilla.
RHEL Engineering is moving the tracking of its product development work on RHEL 6 through RHEL 9 to Red Hat Jira (issues.redhat.com). If you're a Red Hat customer, please continue to file support cases via the Red Hat customer portal. If you're not, please head to the "RHEL project" in Red Hat Jira and file new tickets here. Individual Bugzilla bugs in the statuses "NEW", "ASSIGNED", and "POST" are being migrated throughout September 2023. Bugs of Red Hat partners with an assigned Engineering Partner Manager (EPM) are migrated in late September as per pre-agreed dates. Bugs against components "kernel", "kernel-rt", and "kpatch" are only migrated if still in "NEW" or "ASSIGNED". If you cannot log in to RH Jira, please consult article #7032570. That failing, please send an e-mail to the RH Jira admins at rh-issues@redhat.com to troubleshoot your issue as a user management inquiry. The email creates a ServiceNow ticket with Red Hat. Individual Bugzilla bugs that are migrated will be moved to status "CLOSED", resolution "MIGRATED", and set with "MigratedToJIRA" in "Keywords". The link to the successor Jira issue will be found under "Links", have a little "two-footprint" icon next to it, and direct you to the "RHEL project" in Red Hat Jira (issue links are of type "https://issues.redhat.com/browse/RHEL-XXXX", where "X" is a digit). This same link will be available in a blue banner at the top of the page informing you that that bug has been migrated.

Bug 1853847

Summary: severe performance degradation when using -s with tree command
Product: Red Hat Enterprise Linux 8 Reporter: John Pittman <jpittman>
Component: crashAssignee: ltao
Status: CLOSED WONTFIX QA Contact: xiaoying yan <yiyan>
Severity: medium Docs Contact:
Priority: unspecified    
Version: 8.1CC: cye, djeffery, dwysocha, kdump-bugs, ruyang, stalexan, xiawu
Target Milestone: rcKeywords: Triaged
Target Release: 8.0Flags: pm-rhel: mirror+
Hardware: x86_64   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2021-09-07 01:25:59 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On:    
Bug Blocks: 1674330, 1888160    

Description John Pittman 2020-07-04 16:51:15 UTC
Description of problem:

severe performance degradation when using -s with tree command

Version-Release number of selected component (if applicable):

crash-7.2.7-3.el8.x86_64

How reproducible:

Every time

Actual results:

Command takes an extraordinary amount of time

Expected results:

Command should complete in a reasonable amount of time

Additional info:

In the vmcore, 'tree -t rbtree -N 0xffff8bb3fb3d4cc0 >/dev/null' takes a couple seconds; there are about 55,000 entries.  However, with the addition of the -s flag, 'tree -t rbtree -N 0xffff8bb3fb3d4cc0 -s iova.pfn_lo,pfn_hi >/dev/null' takes over an hour to complete.

We created a pykdump script and it completes the same operation in about 4 seconds, printing identical output.

def for_all_rbtree(root, sname = None, smember = None):
    node = rb_first(root)
    while (node):
        if (sname):
            yield  container_of(node, sname, smember)
        else:
            yield node
        node = rb_next(node)

dma_ops = long(0xffff8c4a78d42000)
dma = readSU("struct dma_ops_domain", dma_ops)
iovad = dma.iovad
for iova in for_all_rbtree(iovad.rbroot, "struct iova", "node"):
    print("{:#x}".format(iova))
    print(" pfn_hi =  {}".format(iova.pfn_hi))
    print(" pfn_lo =  {}".format(iova.pfn_lo))

crash> epython /home/rdu/jpittman/testscript.py
0xffff8bb40296ee80
 pfn_hi =  7
 pfn_lo =  4
0xffff8bb4685ac6c0
 pfn_hi =  15
 pfn_lo =  12
[....]
0xffff8bb451ee3100
 pfn_hi =  4503599627370479
 pfn_lo =  4503599627370464
0xffff8bb451ee3fc0
 pfn_hi =  4503599627370495
 pfn_lo =  4503599627370480
0xffff8c4a78d42178
 pfn_hi =  18446744073709551615
 pfn_lo =  18446744073709551615
 ** Execution took   3.87s (real)   3.72s (CPU), Child processes:   0.13s

Comment 5 Bhupesh Sharma 2020-10-21 21:46:24 UTC
(In reply to John Pittman from comment #0)
> Description of problem:
> 
> severe performance degradation when using -s with tree command
> 
> Version-Release number of selected component (if applicable):
> 
> crash-7.2.7-3.el8.x86_64
> 
> How reproducible:
> 
> Every time
> 
> Actual results:
> 
> Command takes an extraordinary amount of time
> 
> Expected results:
> 
> Command should complete in a reasonable amount of time
> 
> Additional info:
> 
> In the vmcore, 'tree -t rbtree -N 0xffff8bb3fb3d4cc0 >/dev/null' takes a
> couple seconds; there are about 55,000 entries.  However, with the addition
> of the -s flag, 'tree -t rbtree -N 0xffff8bb3fb3d4cc0 -s iova.pfn_lo,pfn_hi
> >/dev/null' takes over an hour to complete.
> 
> We created a pykdump script and it completes the same operation in about 4
> seconds, printing identical output.
> 
> def for_all_rbtree(root, sname = None, smember = None):
>     node = rb_first(root)
>     while (node):
>         if (sname):
>             yield  container_of(node, sname, smember)
>         else:
>             yield node
>         node = rb_next(node)
> 
> dma_ops = long(0xffff8c4a78d42000)
> dma = readSU("struct dma_ops_domain", dma_ops)
> iovad = dma.iovad
> for iova in for_all_rbtree(iovad.rbroot, "struct iova", "node"):
>     print("{:#x}".format(iova))
>     print(" pfn_hi =  {}".format(iova.pfn_hi))
>     print(" pfn_lo =  {}".format(iova.pfn_lo))
> 
> crash> epython /home/rdu/jpittman/testscript.py
> 0xffff8bb40296ee80
>  pfn_hi =  7
>  pfn_lo =  4
> 0xffff8bb4685ac6c0
>  pfn_hi =  15
>  pfn_lo =  12
> [....]
> 0xffff8bb451ee3100
>  pfn_hi =  4503599627370479
>  pfn_lo =  4503599627370464
> 0xffff8bb451ee3fc0
>  pfn_hi =  4503599627370495
>  pfn_lo =  4503599627370480
> 0xffff8c4a78d42178
>  pfn_hi =  18446744073709551615
>  pfn_lo =  18446744073709551615
>  ** Execution took   3.87s (real)   3.72s (CPU), Child processes:   0.13s

Hello,

I cannot seem to reproduce this with both 'crash version: 7.2.8-7.el8' and 'crash version: 7.2.7-3.el8' with vmcores obtained on hpe x86_64 and kvm x86_64 machines:

crash> whatis vmap_area_root

crash> p vmap_area_root
vmap_area_root = $1 = {
  rb_node = 0xffff9619a6554d38
}

crash> tree -t rbtree -N 0xffff9619a6554d38 >/dev/null

.. completes in a few seconds ..

crash> tree -t rbtree -N 0xffff9619a6554d38 -s iova.pfn_lo,pfn_hi >/dev/null

.. completes in a few seconds ..


Can you please share the following so that this can be reproduced / fixed?:
1. vmcore file (it's no longer available on 'galvatron' machine)
2. 'home/rdu/jpittman/testscript.py' test script.

If you can attach the same to the BZ, it would really help.

Thanks,
Bhupesh

Comment 17 Dave Wysochanski 2021-04-19 13:27:50 UTC
(In reply to ltao from comment #15)
> Hello,
> 
> I have created a fix, which can shorten the overall run time from 1.5h to
> 40min,

<snip>

> 
> But the fix is only a proof-of-concept, it still takes 40min to finish when
> comparing with
> a few seconds by pykdump script.
> 
> I haven't tried pykdump yet, may need more time to figure out why it takes
> less time. 
> I'm wondering if the current time consuming improvement is acceptable?
> 

This looks like forward progress which is always good!  However, it cannot be evaluated because there is no patch.  Also I doubt that is quite enough performance improvement if pykdump truly only takes only 4 seconds (keep in mind pykdump caches results, so I'm not sure if the 4s was an uncached run or a cached run).

Unless John wants to respond directly since he filed the bug, the best way forward is probably to post to upstream crash-utility list, as a "RFC PATCH 1/1" and ask for feedback, assuming this is still reproducible with upstream crash version?

In addition to patch, probably you will need a "RFC PATCH 0/1" (introduction cover letter to explain "proof of concept" patch, as well as the high-level problem - pykdump difference in performance once that is confirmed).

Comment 18 John Pittman 2021-04-19 14:31:14 UTC
Hi Dave, Emma, Tao,

Thanks for the response and sorry for the delay.  The improvement is a good one, but I don't think it's drastic enough to be called a fix.  As Dave mentioned, pykdump can cache results, so I did a test to make sure it wasn't.  I edited the script to show the below:

[jpittman@galvatron ~]$ cat /home/rdu/jpittman/testscript.py
from pykdump.API import *
from LinuxDump.trees import *
def for_all_rbtree(root, sname = None, smember = None):
    node = rb_first(root)
    while (node):
        if (sname):
            yield  container_of(node, sname, smember)
        else:
            yield node
        node = rb_next(node)

dma_ops = long(0xffff8c4a78d42000)
dma = readSU("struct dma_ops_domain", dma_ops)
iovad = dma.iovad
for iova in for_all_rbtree(iovad.rbroot, "struct iova", "node"):
    print("{:#x}".format(iova))
    print(" pfn_hi =  {}".format(iova.pfn_hi))
    print(" pfn_lo =  {}".format(iova.pfn_lo))

And ran it as the first command after the vmcore was loaded to make sure it didn't have anything cached yet.

[jpittman@galvatron ~]$ retrace-server-interact 156657913 crash
If you want to execute the command manually, you can run
$ /cores/crashext/gitlab-runner/bin/crash -i /cores/retrace/tasks/156657913/crashrc /cores/retrace/tasks/156657913/crash/vmcore /cores/retrace/repos/kernel/x86_64/usr/lib/debug/lib/modules/3.10.0-1062.18.1.el7.x86_64/vmlinux

....snip

crash> extend /cores/crashext/mpykdumpppc64.so
extend: /cores/crashext/mpykdumpppc64.so: not an ELF format object file
crash> cd /cores/retrace/tasks/156657913/results
Working directory /cores/retrace/tasks/156657913/results.
crash> epython /home/rdu/jpittman/testscript.py | head
0xffff8bb40296ee80
 pfn_hi =  7
 pfn_lo =  4
0xffff8bb4685ac6c0
 pfn_hi =  15
 pfn_lo =  12
0xffff8bb3f7786b00
 pfn_hi =  19
 pfn_lo =  18

....snip

0xffff8bb451ee3100
 pfn_hi =  4503599627370479
 pfn_lo =  4503599627370464
0xffff8bb451ee3fc0
 pfn_hi =  4503599627370495
 pfn_lo =  4503599627370480
0xffff8c4a78d42178
 pfn_hi =  18446744073709551615
 pfn_lo =  18446744073709551615

 ** Execution took   3.13s (real)   3.12s (CPU)

So, we can see it still only took a little over 3 seconds.

Comment 19 ltao 2021-04-21 01:31:05 UTC
Hi Dave, John, Emma,

Thanks so much for the detailed info! I will give it another try and see whether I
can get a better improvement.

Thanks!

Comment 20 ltao 2021-08-04 08:39:10 UTC
Hello,

We can use '-S' instead of '-s' in the crash tree cmd, which can finish in a few seconds and get the identical output as the python script: 

crash> ! date
2021年 08月 04日 星期三 03:57:43 EDT
crash> tree -t rbtree -N 0xffff8bb3fb3d4cc0 -S iova.pfn_lo,pfn_hi > /dev/null
crash> ! date
2021年 08月 04日 星期三 03:57:47 EDT

The difference of -S and -s is, as I quote the man page of crash:

"Similar to -s, but instead of parsing gdb output, member values are read directly from memory."

To illustrate, -s will pass the queries to gdb, in this case, cmds as "output *(struct iova *)0xffff8bb3fb3d4cc0" will be continuously passed to gdb, then gdb will parse the expression according to c language grammer, then evaluate the expression and return it. It is a generic but time-consuming process.

-S will directly read and return the value from memory, without the complex gdb process. If we take an inspection of the python script, it doesn't do the grammer parse neither, just read and return value from memory. At this level, crash and the python script have the same performance.

Any thoughs?

Thanks,
Tao Liu

Comment 24 ltao 2021-08-05 08:47:58 UTC
Hello Dave,

I made another performance test against the gdb-10.2 crash:

[ltao@galvatron ~]$ ./crash-c0e54e9 /cores/retrace/tasks/156657913/crash/vmcore /cores/retrace/repos/kernel/x86_64/usr/lib/debug/lib/modules/3.10.0-1062.18.1.el7.x86_64/vmlinux

crash-c0e54e9> ! date
2021年 08月 05日 星期四 03:25:58 EDT
crash-c0e54e9> tree -t rbtree -N 0xffff8bb3fb3d4cc0 -s iova.pfn_lo,pfn_hi > /dev/null
crash-c0e54e9> ! date
2021年 08月 05日 星期四 04:33:09 EDT    <---- 1h8min

When comparing with the original gdb-7.6 crash of comment15:

crash> !date
2021年 04月 13日 星期二 08:10:12 EDT
crash> tree -t rbtree -N 0xffff8bb3fb3d4cc0 -s iova.pfn_lo,pfn_hi > /dev/null
crash> !date
2021年 04月 13日 星期二 09:44:40 EDT   <---- 1h34min

The performance has improved a little for gdb-10.2

Thanks,
Tao Liu

Comment 25 John Pittman 2021-08-20 18:42:25 UTC
Thanks Tao! And sorry for the wait. Great find.  In my tests it works very well.  Is there a reason why both -s and -S exists?  Could one be eliminated and only use the process shown in -S?  If no, is it possible to add in the crash man page that -s can be slow?  Thanks again for the great workaround.

Comment 26 ltao 2021-08-23 01:52:04 UTC
Hello John,

There are reasons for -s and -S co-exist. As the "help tree" outputs:

-S struct:  Similar to -s, but instead of parsing gdb output, member values
            are read directly from memory, so the command works much faster
            for 1-, 2-, 4-, and 8-byte members.

the type of iova.pfn_lo,pfn_hi are unsigned long, so -S is more suitable for them. 

-S only works for specific cases. -s is a generic process, works for all cases, but slower.


Thanks,
Tao Liu