linux-perf-users.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* perf and gprof2dot
@ 2011-10-17 16:38 Mark Hills
  2011-10-17 23:30 ` Arun Sharma
  0 siblings, 1 reply; 3+ messages in thread
From: Mark Hills @ 2011-10-17 16:38 UTC (permalink / raw)
  To: linux-perf-users

I'm using perf very successfully, and recently in place of oprofile.

But I wondered if there is a way for 'perf report' to output a gprof-style 
callgraph (similar to 'oprofile -c')?

Aside from being familiar, the motivation is so that it can be displayed 
as a directed graph (not tree) by the excellent gprof2dot [1] tool.

Many thanks

[1] http://code.google.com/p/jrfonseca/wiki/Gprof2Dot

-- 
Mark

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: perf and gprof2dot
  2011-10-17 16:38 perf and gprof2dot Mark Hills
@ 2011-10-17 23:30 ` Arun Sharma
  2011-10-19 14:34   ` Mark Hills
  0 siblings, 1 reply; 3+ messages in thread
From: Arun Sharma @ 2011-10-17 23:30 UTC (permalink / raw)
  To: Mark Hills; +Cc: linux-perf-users

On Mon, Oct 17, 2011 at 05:38:22PM +0100, Mark Hills wrote:
> I'm using perf very successfully, and recently in place of oprofile.
> 
> But I wondered if there is a way for 'perf report' to output a gprof-style 
> callgraph (similar to 'oprofile -c')?
> 
> Aside from being familiar, the motivation is so that it can be displayed 
> as a directed graph (not tree) by the excellent gprof2dot [1] tool.

perf record -ag -- sleep 1
perf script | script-below.py | gprof2dot -f hprof | dot -Tpng -o graph.png

It's probably better to teach gprof2dot how to parse the output of perf
script. But this was the path of least resistance for me.

I've seen gprof2dot choke on large input sets though.

 -Arun

#!/usr/bin/env python

"""
Generate hprof compatible sample output so we could feed this into gprof2dot.py -f hprof
"""

import re, string, sys
from optparse import OptionParser
from operator import itemgetter

class KernelSample:
    def __init__(self):
	pass

chain_re = re.compile('^\s*(?P<ip>\S+)\s+(?P<sym>.*)')
def process(file):
    global traces
    rdata = file.read()
    rdata = rdata.split('\n\n')
    for chain in rdata:
        ips = []
        try:
            for line in chain.splitlines()[1:]:
		mod_index = line.rfind('(')
		if mod_index != -1:
		    module = line[mod_index:]
		    line = line[:mod_index]
		else:
		    module = ''
		m = chain_re.match(line)
		ip = ''
		if m: 
		    #print module, m.group('ip'), m.group('sym')
		    ip = m.group('sym') 
                if module.find('kernel') != -1:
                    raise KernelSample()
    	        # strip parens
    	        module = module[1:-1]
                ips.append((ip, module))
        except KernelSample:
    	    continue
	if options.filter:
	    ignore = 1
	    for ip, module in ips:
	        if options.filter.match(ip):
		    ignore = 0
	    if ignore: continue
        trace = tuple(ips)
        if trace in traces.keys():
            traces[trace] += 1
        else:
            traces[trace] = 1

if __name__ == '__main__':
    parser = OptionParser()
    parser.add_option("-q", "--quiet",
                      action="store_false", dest="verbose", default=True,
                      help="don't print status messages to stdout")
    parser.add_option("-t", "--threshold", dest="threshold", default=1,
                      help="Ignore traces that have counts less than this")
    parser.add_option("-p", "--top", dest="top", default=-1,
                      help="Consider only the top N traces")
    parser.add_option("-f", "--filter", dest="filter", default=None,
                      help="Consider only traces that match this regex")

    (options, args) = parser.parse_args()
    if options.filter:
        options.filter = re.compile(options.filter)
    traces = {}
    for file in args:
	process(open(file))

    if not args:
	process(sys.stdin)
  
    options.top = int(options.top)
    traces = sorted(traces.iteritems(), key=itemgetter(1), reverse=True)
    if options.top != -1: traces = traces[:options.top]

    map = {} 
    print '-------' 
    count = 0
    for trace, hits in traces:
	map[trace] = count
        print "TRACE %d:" % count
	count += 1
        for frame in trace:
    	    ip, module = frame
	    print "\t%s (%s:0)" % (ip, module)

    print 'blah'
    print 'blah'
    print 'CPU blah'
    for trace, count in traces:
	id = map[trace]
        #rank, percent_self, percent_accum, count, traceid, method
	try:
            print '1 1 1 %d %d %s' % (count, id, trace[0][0])
	except:
	    import traceback
	    print trace
	    #traceback.print_exc(file=sys.stderr)
	    continue

    print 'CPU blah'

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: perf and gprof2dot
  2011-10-17 23:30 ` Arun Sharma
@ 2011-10-19 14:34   ` Mark Hills
  0 siblings, 0 replies; 3+ messages in thread
From: Mark Hills @ 2011-10-19 14:34 UTC (permalink / raw)
  To: Arun Sharma; +Cc: linux-perf-users

On Mon, 17 Oct 2011, Arun Sharma wrote:

> On Mon, Oct 17, 2011 at 05:38:22PM +0100, Mark Hills wrote:
> > I'm using perf very successfully, and recently in place of oprofile.
> > 
> > But I wondered if there is a way for 'perf report' to output a gprof-style 
> > callgraph (similar to 'oprofile -c')?
> > 
> > Aside from being familiar, the motivation is so that it can be displayed 
> > as a directed graph (not tree) by the excellent gprof2dot [1] tool.
> 
> perf record -ag -- sleep 1
> perf script | script-below.py | gprof2dot -f hprof | dot -Tpng -o graph.png

Thanks Arun, interesting script.
 
> It's probably better to teach gprof2dot how to parse the output of perf 
> script. But this was the path of least resistance for me.

Since we spoke, the author of gprof2dot has added preliminary support for 
perf to his repository. It's not fully complete and is just a test; eg. 
the call ratios are wrong as gprof2dot expects them from the caller (not 
callee) perspective.

  $ perf report --show-nr-samples -g flat,0 | gprof2dot -f perf

I did not have chance to look at what extra work is needed, but the 
initial results are promising.

-- 
Mark

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2011-10-19 14:34 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-10-17 16:38 perf and gprof2dot Mark Hills
2011-10-17 23:30 ` Arun Sharma
2011-10-19 14:34   ` Mark Hills

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).