view mercurial/lsprofcalltree.py @ 25867:a74e9806d17d stable

highlight: produce correct markup when there's a blank line just before EOF Due to how the colorized output from pygments was stripped of <pre> elements, when there was an empty line at the end of a file, highlight extension produced an incorrect markup (no closing tags from the fileline/annotateline template). It wasn't usually noticeable, because browsers were smart enough to see where the missing tags should've been, but in monoblue style it resulted in the last line having twice the normal height. Instead of awkwardly trying to strip outer <pre></pre> tags, let's make the formatter with nowrap=True, which should do what we need in pygments since at least 0.5 (2006-10-30). Example from monoblue style: Before: <div class="source"> <div style="font-family:monospace" class="parity0"> <pre><a class="linenr" href="#l1" id="l1"> 1</a> </pre> </div> <div style="font-family:monospace" class="parity1"> <pre><a class="linenr" href="#l2" id="l2"> 2</a> </div> Now: <div class="source"> <div style="font-family:monospace" class="parity0"> <pre><a class="linenr" href="#l1" id="l1"> 1</a> </pre> </div> <div style="font-family:monospace" class="parity1"> <pre><a class="linenr" href="#l2" id="l2"> 2</a> </pre> </div> </div> (Notice the missing </pre></div> now in place)
author Anton Shestakov <av6@dwimlabs.net>
date Wed, 22 Jul 2015 10:19:17 +0800
parents beae42f3d93b
children 071af8d385a9
line wrap: on
line source

"""
lsprofcalltree.py - lsprof output which is readable by kcachegrind

Authors:
    * David Allouche <david <at> allouche.net>
    * Jp Calderone & Itamar Shtull-Trauring
    * Johan Dahlin

This software may be used and distributed according to the terms
of the GNU General Public License, incorporated herein by reference.
"""

def label(code):
    if isinstance(code, str):
        return '~' + code    # built-in functions ('~' sorts at the end)
    else:
        return '%s %s:%d' % (code.co_name,
                             code.co_filename,
                             code.co_firstlineno)

class KCacheGrind(object):
    def __init__(self, profiler):
        self.data = profiler.getstats()
        self.out_file = None

    def output(self, out_file):
        self.out_file = out_file
        print >> out_file, 'events: Ticks'
        self._print_summary()
        for entry in self.data:
            self._entry(entry)

    def _print_summary(self):
        max_cost = 0
        for entry in self.data:
            totaltime = int(entry.totaltime * 1000)
            max_cost = max(max_cost, totaltime)
        print >> self.out_file, 'summary: %d' % (max_cost,)

    def _entry(self, entry):
        out_file = self.out_file

        code = entry.code
        #print >> out_file, 'ob=%s' % (code.co_filename,)
        if isinstance(code, str):
            print >> out_file, 'fi=~'
        else:
            print >> out_file, 'fi=%s' % (code.co_filename,)
        print >> out_file, 'fn=%s' % (label(code),)

        inlinetime = int(entry.inlinetime * 1000)
        if isinstance(code, str):
            print >> out_file, '0 ', inlinetime
        else:
            print >> out_file, '%d %d' % (code.co_firstlineno, inlinetime)

        # recursive calls are counted in entry.calls
        if entry.calls:
            calls = entry.calls
        else:
            calls = []

        if isinstance(code, str):
            lineno = 0
        else:
            lineno = code.co_firstlineno

        for subentry in calls:
            self._subentry(lineno, subentry)
        print >> out_file

    def _subentry(self, lineno, subentry):
        out_file = self.out_file
        code = subentry.code
        #print >> out_file, 'cob=%s' % (code.co_filename,)
        print >> out_file, 'cfn=%s' % (label(code),)
        if isinstance(code, str):
            print >> out_file, 'cfi=~'
            print >> out_file, 'calls=%d 0' % (subentry.callcount,)
        else:
            print >> out_file, 'cfi=%s' % (code.co_filename,)
            print >> out_file, 'calls=%d %d' % (
                subentry.callcount, code.co_firstlineno)

        totaltime = int(subentry.totaltime * 1000)
        print >> out_file, '%d %d' % (lineno, totaltime)