app/app_profiler/ppstats.py
author Mario Ferraro <fadinlight@gmail.com>
Sun, 15 Nov 2009 22:12:20 +0100
changeset 3093 d1be59b6b627
parent 2857 bc793800116e
permissions -rw-r--r--
GMaps related JS changed to use new google namespace. Google is going to change permanently in the future the way to load its services, so better stay safe. Also this commit shows uses of the new melange.js module. Fixes Issue 634.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2832
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
     1
import pstats
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
     2
import cPickle
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
     3
import zlib
2857
bc793800116e Updated to r11 of app_profiler
Sverre Rabbelier <srabbelier@gmail.com>
parents: 2832
diff changeset
     4
import re
2832
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
     5
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
     6
class PickleStats(object):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
     7
    def __init__(self, stats):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
     8
        self.stats = stats
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
     9
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    10
    def create_stats(self):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    11
        "pstats.Stats checks for the existence of this method to see if it can load from an object"
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    12
        pass
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    13
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    14
def from_file(fileobj):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    15
    "load ppstats from an open file object"
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    16
    stats = cPickle.load(fileobj)
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    17
    ps = PickleStats(stats)
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    18
    return Stats(ps)
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    19
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    20
def from_filename(filename):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    21
    "load ppstats from a filename"
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    22
    fileobj = open(filename, 'rb')
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    23
    return from_file(fileobj)
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    24
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    25
def from_gz_file(fileobj):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    26
    "load ppstats from an open file containing gzipped data"
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    27
    data = fileobj.read()
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    28
    stats = cPickle.loads(zlib.decompress(data))
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    29
    ps = PickleStats(stats)
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    30
    return Stats(ps)
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    31
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    32
def from_gz_filename(filename):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    33
    "load ppstats from a file containing gzipped data, by filename"
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    34
    fileobj = open(filename, 'rb')
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    35
    return from_gz_file(fileobj)
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    36
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    37
def from_gz(gz_string):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    38
    "load ppstats from a string of gzipped data"
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    39
    return Stats(PickleStats(cPickle.loads(zlib.decompress(gz_string))))
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    40
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    41
def from_stats(stats):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    42
    "load ppstats from a stats object" 
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    43
    return Stats(PickleStats(stats))
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    44
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    45
def from_string(stats_string):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    46
    return Stats(PickleStats(cPickle.loads(stats_string)))
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    47
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    48
class Stats(pstats.Stats):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    49
    def __init__(self, *args, **kwargs):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    50
        pstats.Stats.__init__(self, *args)
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    51
        self.replace_dirs = {}
2857
bc793800116e Updated to r11 of app_profiler
Sverre Rabbelier <srabbelier@gmail.com>
parents: 2832
diff changeset
    52
        self.replace_regexes = {}
2832
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    53
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    54
    def set_output(self, stream):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    55
        "redirect output of print_stats to the file object <stream>"
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    56
        self.stream = stream
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    57
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    58
    def hide_directory(self, dirname, replacement=''):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    59
        "replace occurences of <dirname> in filenames with <replacement>"
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    60
        self.replace_dirs[dirname] = replacement
2857
bc793800116e Updated to r11 of app_profiler
Sverre Rabbelier <srabbelier@gmail.com>
parents: 2832
diff changeset
    61
        
bc793800116e Updated to r11 of app_profiler
Sverre Rabbelier <srabbelier@gmail.com>
parents: 2832
diff changeset
    62
    def hide_regex(self, pattern, replacement=''):
bc793800116e Updated to r11 of app_profiler
Sverre Rabbelier <srabbelier@gmail.com>
parents: 2832
diff changeset
    63
        "call re.sub(pattern, replacement) on each filename"
bc793800116e Updated to r11 of app_profiler
Sverre Rabbelier <srabbelier@gmail.com>
parents: 2832
diff changeset
    64
        self.replace_regexes[pattern] = replacement
2832
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    65
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    66
    def func_strip_path(self, func_name):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    67
        "take a filename, line, name tuple and mangle appropiately"
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    68
        filename, line, name = func_name
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    69
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    70
        for dirname in self.replace_dirs:
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    71
            filename = filename.replace(dirname, self.replace_dirs[dirname])
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    72
2857
bc793800116e Updated to r11 of app_profiler
Sverre Rabbelier <srabbelier@gmail.com>
parents: 2832
diff changeset
    73
        for pattern in self.replace_regexes:
bc793800116e Updated to r11 of app_profiler
Sverre Rabbelier <srabbelier@gmail.com>
parents: 2832
diff changeset
    74
            filename = re.sub(pattern, self.replace_regexes[pattern], filename)
bc793800116e Updated to r11 of app_profiler
Sverre Rabbelier <srabbelier@gmail.com>
parents: 2832
diff changeset
    75
2832
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    76
        return filename, line, name
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    77
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    78
    def strip_dirs(self):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    79
        "strip irrelevant/redundant directories from filenames in profile data"
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    80
        func_std_string = pstats.func_std_string
2857
bc793800116e Updated to r11 of app_profiler
Sverre Rabbelier <srabbelier@gmail.com>
parents: 2832
diff changeset
    81
        add_func_stats = pstats.add_func_stats
2832
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    82
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    83
        oldstats = self.stats
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    84
        self.stats = newstats = {}
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    85
        max_name_len = 0
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    86
        for func, (cc, nc, tt, ct, callers) in oldstats.iteritems():
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    87
            newfunc = self.func_strip_path(func)
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    88
            if len(func_std_string(newfunc)) > max_name_len:
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    89
                max_name_len = len(func_std_string(newfunc))
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    90
            newcallers = {}
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    91
            for func2, caller in callers.iteritems():
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    92
                newcallers[self.func_strip_path(func2)] = caller
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    93
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    94
            if newfunc in newstats:
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    95
                newstats[newfunc] = add_func_stats(
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    96
                                        newstats[newfunc],
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    97
                                        (cc, nc, tt, ct, newcallers))
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    98
            else:
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
    99
                newstats[newfunc] = (cc, nc, tt, ct, newcallers)
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   100
        old_top = self.top_level
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   101
        self.top_level = new_top = {}
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   102
        for func in old_top:
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   103
            new_top[self.func_strip_path(func)] = None
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   104
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   105
        self.max_name_len = max_name_len
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   106
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   107
        self.fcn_list = None
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   108
        self.all_callees = None
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   109
        return self
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   110
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   111
    def dump_stats_pickle(self):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   112
        "return a string containing picked stats information (dump_stats uses marshall)"
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   113
        return cPickle.dumps(self.stats)
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   114
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   115
    def load_stats_pickle(self, pickle_string):
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   116
        "load from string returned by dump_stats_pickle"
2a0a7e081caf Profiling patch
Sverre Rabbelier <srabbelier@gmail.com>
parents:
diff changeset
   117
        return self.load_stats(PickleStats(cPickle.load(pickle_string)))