Bug 28454 - MI -var-list-children bad performance with simple pretty printers
Summary: MI -var-list-children bad performance with simple pretty printers
Status: UNCONFIRMED
Alias: None
Product: gdb
Classification: Unclassified
Component: varobj (show other bugs)
Version: 9.2
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2021-10-15 08:25 UTC by Andrey Lesnikov
Modified: 2023-08-31 17:09 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments
a zip copy of the https://github.com/ozkriff/gdb_slow_var_list_children repo (1.15 MB, application/zip)
2021-10-15 08:25 UTC, Andrey Lesnikov
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Andrey Lesnikov 2021-10-15 08:25:03 UTC
Created attachment 13722 [details]
a zip copy of the https://github.com/ozkriff/gdb_slow_var_list_children repo

A sample project (sadly, I wasn't able to minimize the sample project further) is based on https://vulkan-tutorial.com/Multisampling Vulkan demo with minor tweaks:

https://github.com/ozkriff/gdb_slow_var_list_children (a zip copy is also attached)

Steps to reproduce the issue:

- clone the gdb_slow_var_list_children repo and cd into it
- `cmake -DCMAKE_BUILD_TYPE=Debug -Btarget`
- `cd target`
- `cmake --build .`
- `gdb -q -ex "source -v ../gdb-commands"`
  The gdb-commands GDB script basically sets up a simple pretty-printer from printers.py, sets a breakpoint, launches the executable and calls -var-list-children that take unexpectedly significant time (up to 6 seconds on my machine with i9-9980HK) to execute despite not doing that much work.


Additional info:

- Ubuntu 20.04.3 LTS
- Linux 5.4.0-88-generic #99-Ubuntu SMP Thu Sep 23 17:29:00 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
- GNU gdb (Ubuntu 9.2-0ubuntu1~20.04) 9.2
- gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
- cmake version 3.16.3


The gdb-commands script:

```
# run with something like "gdb -q -ex "source -v gdb-commands" | gnomon -h 1"

interpreter-exec mi2 "-gdb-set print elements 250"
interpreter-exec mi2 "-gdb-set print repeats 0"
interpreter-exec mi2 "-gdb-set print object on"
interpreter-exec mi2 "-gdb-set print asm-demangle on"
interpreter-exec mi2 "-gdb-set python print-stack full"
interpreter-exec mi2 "-gdb-set backtrace past-main on"
interpreter-exec mi2 "-gdb-show mi-async"
interpreter-exec mi2 "handle SIGSTOP stop nopass"
interpreter-exec mi2 "info pretty-printer"

interpreter-exec mi2 "python import sys; sys.dont_write_bytecode = True;"
interpreter-exec mi2 "python import sys; sys.path.insert(0, \"..\"); from printers import register_default_printers; register_default_printers(None);"
interpreter-exec mi2 "-enable-pretty-printing"

interpreter-exec mi2 "-file-exec-and-symbols "vksample""
interpreter-exec mi2 "-break-insert -f "src/main.cpp:357""

interpreter-exec mi2 "-gdb-set charset UTF-8"
interpreter-exec mi2 "-exec-run"

interpreter-exec mi2 "0-gdb-set $__poke_gdb=1"
interpreter-exec mi2 "-stack-list-frames --thread 1 0 100"
interpreter-exec mi2 "-stack-list-variables --thread 1 --frame 0 --no-values"
interpreter-exec mi2 "-interpreter-exec --thread 1 --frame 0 console \"whatis/mt this\""
interpreter-exec mi2 "-data-evaluate-expression --thread 1 --frame 0 $fp"
interpreter-exec mi2 "-stack-list-frames --thread 1 1 101"

interpreter-exec mi2 "-var-create var1_this * \"this\""
interpreter-exec mi2 "-var-list-children --all-values "var1_this" -1 -1"
interpreter-exec mi2 "-var-list-children --all-values "var1_this.private" 0 44"

quit
```

printers.py:

```
import gdb


def untypedef(type_obj):
    if (type_obj.code == gdb.TYPE_CODE_REF
            or type_obj.code == getattr(gdb, 'TYPE_CODE_RVALUE_REF', None)):
        type_obj = type_obj.target()
    if type_obj.code == gdb.TYPE_CODE_TYPEDEF:
        type_obj = type_obj.strip_typedefs()
    return type_obj


def lookup(val):
    type = untypedef(val.type)
    if type.code == gdb.TYPE_CODE_PTR:
        try:
            dereferenced = val.dereference()
            dereferenced.fetch_lazy()
        except gdb.error as e:
            print('ERROR: ', str(e))
        else:
            delegate = gdb.default_visualizer(dereferenced)
            assert(delegate is None)
            # normally, the delegate would be passed into a custom pretty printer next
    return None


def register_default_printers(obj):
    gdb.printing.register_pretty_printer(obj, lookup)
```


The main.cpp is too big to inline as a text so I'm leaving it in the repo/attachment.