This is the mail archive of the gdb@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

gdb script performance


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

Attachment: gdb-gprof.txt.bz2
Description: Binary data


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]