gdb script performance
Jean-Marc Saffroy
saffroy@gmail.com
Thu Oct 5 12:16:00 GMT 2006
Hello,
I'm using gdb (6.5) to analyse a Linux kernel kdump (really an ELF core
file), and I find that a simple script is awwwfully slow. Here is an
example:
define cntmaps
shell date
set $map = vmlist
set $gcount = 0
while $map != 0
set $gcount = $gcount + 1
set $map = $map->next
end
printf "vmlist count: %d\n", $gcount
shell date
end
(gdb) cntmaps
Thu Oct 5 13:44:04 CEST 2006
vmlist count: 99
Thu Oct 5 13:44:14 CEST 2006
So it takes about 10 seconds to walk a list with ~100 elements, without
doing anything really useful (the host is a 2GHz dual core!). I have
another script that does more complex processing with the same list, and
it takes about 12 minutes to complete! It's the lsmaps macro below, which
ends up calling the vmap macro 2381 times.
So I rebuilt gdb with profiling (-pg), attached is the complete output
from gprof after running lsmaps in batch mode. A quick look suggests that
some symbol lookups are problematic, and I suspect that gdb easily ends up
doing linear searches in some big table (I'm working on a Linux kernel
with full debug infos).
Any suggestion for performance improvement? Maybe gdb could use hash
tables to speed up things a bit? :-)
Cheers,
--
saffroy@gmail.com
# a few useful(?) macros for x86-64 VMM hacks
# useful constants
set $PAGE_SIZE = (1<<12)
set $__PHYSICAL_MASK = (1 << 46)-1
set $PTE_MASK = ~($PAGE_SIZE-1) & $__PHYSICAL_MASK
set $__PAGE_OFFSET = 0xffff810000000000
set $_PAGE_PSE = 0x80
define vmap
set $addr = (long)$arg0
# index in each of the 4 levels of page directories
set $pgd = $addr >> 39 & (1<<9)-1
set $pud = $addr >> 30 & (1<<9)-1
set $pmd = $addr >> 21 & (1<<9)-1
set $pte = $addr >> 12 & (1<<9)-1
# offset in page
set $off = $addr & (1<<12)-1
#printf "%03x %03x %03x %03x %03x\n", $pgd, $pud, $pmd, $pte, $off
set $pgd_off = (pgd_t *) &init_level4_pgt + $pgd
#printf "pgd_off: %lx pgd: %lx\n", $pgd_off, (long)$pgd_off->pgd
set $pgd_page = ((long)$pgd_off->pgd & $PTE_MASK) + $__PAGE_OFFSET
#printf "pgd_page: %lx\n", $pgd_page
set $pud_off = ((pud_t *) $pgd_page) + $pud
#printf "pud_off: %lx pud: %lx\n", $pud_off, (long)$pud_off->pud
set $pud_page = ((long)$pud_off->pud & $PTE_MASK) + $__PAGE_OFFSET
#printf "pud_page: %lx\n", $pud_page
set $pmd_off = ((pmd_t *) $pud_page) + $pmd
#printf "pmd_off: %lx pmd: %lx\n", $pmd_off, (long)$pmd_off->pmd
set $pmd_page = ((long)$pmd_off->pmd & $PTE_MASK) + $__PAGE_OFFSET
#printf "pmd_page: %lx\n", $pmd_page
if ((long)$pmd_off->pmd & $_PAGE_PSE) != 0
#printf "PSE page! "
set $paddr = $pmd_page + ($addr & (1<<21)-1)
else
set $pte_off = ((pte_t *) $pmd_page) + $pte
#printf "pte_off: %lx pte: %lx\n", $pte_off, (long)$pte_off->pte
set $pte_page = ((long)$pte_off->pte & $PTE_MASK) + $__PAGE_OFFSET
#printf "pte_page: %lx\n", $pte_page
set $paddr = $pte_page + $off
end
#printf "remapped physical addr: %lx\n", $paddr
printf "%lx -> %lx\n", $addr, $paddr
end
define lsmaps
set $map = vmlist
set $gcount = 0
while $map != 0
if $map->pages != 0
set $vaddr = (long)$map->addr
set $count = (long)$map->size / $PAGE_SIZE
set $gcount = $gcount + $count -1
while $count > 1
vmap $vaddr
set $vaddr = $vaddr + $PAGE_SIZE
set $count = $count - 1
end
end
set $map = $map->next
end
printf "page count: %d\n", $gcount
end
-------------- next part --------------
A non-text attachment was scrubbed...
Name: gdb-gprof.txt.bz2
Type: application/octet-stream
Size: 63566 bytes
Desc:
URL: <http://sourceware.org/pipermail/gdb/attachments/20061005/2f942dac/attachment.obj>
More information about the Gdb
mailing list