def _entry(self, entry): out_file = self.out_file code = entry.code co_filename, co_firstlineno, co_name = cProfile.label(code) if co_filename != '~' and co_firstlineno != 0: out_file.write('fl=%s\nfn=%s\n' % (co_filename, co_name)) else: out_file.write('fn=%s\n' % co_name) inlinetime = int(entry.inlinetime * 1000) if is_basestring(code): out_file.write('0 %s\n' % inlinetime) else: out_file.write('%d %d\n' % (code.co_firstlineno, inlinetime)) # recursive calls are counted in entry.calls if entry.calls: calls = entry.calls else: calls = [] if is_basestring(code): lineno = 0 else: lineno = code.co_firstlineno for subentry, call_info in calls: self._subentry(lineno, subentry, call_info) out_file.write('\n')
def _entry(self, entry): out_file = self.out_file code = entry.code # print >> out_file, 'ob=%s' % (code.co_filename,) co_filename, co_firstlineno, co_name = cProfile.label(code) print('fi=%s' % (co_filename, ), file=out_file) print('fn=%s %s:%d' % (co_name, co_filename, co_firstlineno), file=out_file) inlinetime = int(entry.inlinetime * 1000) if isinstance(code, str): print('0 ', inlinetime, file=out_file) else: print('%d %d' % (code.co_firstlineno, inlinetime), file=out_file) # 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, call_info in calls: self._subentry(lineno, subentry, call_info) print(file=out_file)
def _output_subentry(self, lineno, code, callcount, totaltime): out_file = self.out_file co_filename, co_firstlineno, co_name = cProfile.label(code) munged_name = self.munged_function_name(code) out_file.write('cfl=%s\ncfn=%s\n' % (co_filename, munged_name)) out_file.write('calls=%d %d\n' % (callcount, co_firstlineno)) out_file.write('%d %d\n' % (lineno, totaltime))
def _entry(self, entry): out_file = self.out_file code = entry.code #print >> out_file, 'ob=%s' % (code.co_filename,) co_filename, co_firstlineno, co_name = cProfile.label(code) print >> out_file, 'fi=%s' % (co_filename,) print >> out_file, 'fn=%s %s:%d' % ( co_name, co_filename, co_firstlineno) 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, call_info in calls: self._subentry(lineno, subentry, call_info) print >> out_file
def _entry(self, entry): out_file = self.out_file code = entry.code co_filename, co_firstlineno, co_name = cProfile.label(code) if co_filename != '~' and co_firstlineno != 0: out_file.write('fn=%s %s:%d\n' % ( co_name, co_filename, co_firstlineno)) else: out_file.write('fn=%s\n' % co_name) inlinetime = int(entry.inlinetime * 1000) if is_basestring(code): out_file.write('0 %s\n' % inlinetime) else: out_file.write('%d %d\n' % (code.co_firstlineno, inlinetime)) # recursive calls are counted in entry.calls if entry.calls: calls = entry.calls else: calls = [] if is_basestring(code): lineno = 0 else: lineno = code.co_firstlineno for subentry, call_info in calls: self._subentry(lineno, subentry, call_info) out_file.write('\n')
def _from_entry(self, entry): '''copied from source code of cProfile''' self.key = cProfile.label(entry.code) # directory, line, function_name self.total_calls = entry.callcount # ncalls column of pstats (before '/') self.nrec_calls = self.total_calls - entry.reccallcount # ncalls column of pstats (after '/') self.inline_time = entry.inlinetime # tottime column of pstats self.total_time = entry.totaltime # cumtime column of pstats if self.total_time < self.inline_time: print("Total time is < inline" + str((self.total_time, self.inline_time)))
def _subentry(self, lineno, subentry, call_info): out_file = self.out_file code = subentry.code #print >> out_file, 'cob=%s' % (code.co_filename,) co_filename, co_firstlineno, co_name = cProfile.label(code) print >> out_file, 'cfn=%s %s:%d' % ( co_name, co_filename, co_firstlineno) print >> out_file, 'cfi=%s' % (co_filename,) print >> out_file, 'calls=%d %d' % (call_info[0], co_firstlineno) totaltime = int(call_info[3] * 1000) print >> out_file, '%d %d' % (lineno, totaltime)
def _subentry(self, lineno, subentry, call_info): out_file = self.out_file code = subentry.code co_filename, co_firstlineno, co_name = cProfile.label(code) if co_filename != '~' and co_firstlineno != 0: out_file.write('cfl=%s\ncfn=%s\n' % (co_filename, co_name)) else: out_file.write('cfn=%s\n' % co_name) out_file.write('calls=%d %d\n' % (call_info[0], co_firstlineno)) totaltime = int(call_info[3] * 1000) out_file.write('%d %d\n' % (lineno, totaltime))
def _subentry(self, lineno, subentry, call_info): out_file = self.out_file code = subentry.code # print >> out_file, 'cob=%s' % (code.co_filename,) co_filename, co_firstlineno, co_name = cProfile.label(code) print('cfn=%s %s:%d' % (co_name, co_filename, co_firstlineno), file=out_file) print('cfi=%s' % (co_filename, ), file=out_file) print('calls=%d %d' % (call_info[0], co_firstlineno), file=out_file) totaltime = int(call_info[3] * 1000) print('%d %d' % (lineno, totaltime), file=out_file)
def _subentry(self, lineno, subentry, call_info): out_file = self.out_file code = subentry.code co_filename, co_firstlineno, co_name = cProfile.label(code) if co_filename != '~' and co_firstlineno != 0: out_file.write('cfn=%s %s:%d\n' % ( co_name, co_filename, co_firstlineno)) else: out_file.write('cfn=%s\n' % co_name) out_file.write('calls=%d %d\n' % (call_info[0], co_firstlineno)) totaltime = int(call_info[3] * 1000) out_file.write('%d %d\n' % (lineno, totaltime))
def parse_calls(data): """Helper to convert serialized pstats back to a list of raw entries Converse opperation of cProfile.Profile.snapshot_stats() Slightly modified version of : https://bitbucket.org/ogrisel/pyprof2calltree/src/68edcd9f02e4/pyprof2calltree.py """ entries = dict() allcallers = dict() # first pass over stats to build the list of entry instances for code_info, call_info in data.stats.items(): # build a fake code object code = Code() code.co_filename, code.co_firstlineno, code.co_name = code_info # build a fake entry object cc, nc, tt, ct, callers = call_info entry = Entry() entry.code = code entry.callcount = cc entry.reccallcount = nc - cc entry.inlinetime = tt entry.totaltime = ct # to be filled during the second pass over stats entry.calls = list() entry.caller = 'Parent' # set this in case there is no caller # collect the new entry entries[code_info] = entry allcallers[code_info] = callers.items() # second pass of stats to plug callees into callers for entry in entries.itervalues(): entry_label = cProfile.label(entry.code) entry_callers = allcallers.get(entry_label, []) for entry_caller, call_info in entry_callers: # The caller attribute is used by the treemap to refer to the # 'parent' caller. entries[entry_label].caller = '%s:%s' % (entry_caller[0], entry_caller[2]) entries[entry_caller].calls.append((entry, call_info)) return entries.values()
def pstats2entries(data): """Helper to convert serialized pstats back to a list of raw entries. Converse operation of cProfile.Profile.snapshot_stats() """ # Each entry's key is a tuple of (filename, line number, function name) entries = dict() allcallers = dict() # first pass over stats to build the list of entry instances for code_info, call_info in list(data.stats.items()): # build a fake code object code = Code(*code_info) # build a fake entry object. entry.calls will be filled during the # second pass over stats cc, nc, tt, ct, callers = call_info entry = Entry(code, callcount=cc, reccallcount=nc - cc, inlinetime=tt, totaltime=ct, calls=list()) # collect the new entry entries[code_info] = entry allcallers[code_info] = list(callers.items()) # second pass of stats to plug callees into callers for entry in entries.values(): entry_label = cProfile.label(entry.code) entry_callers = allcallers.get(entry_label, []) for entry_caller, call_info in entry_callers: cc, nc, tt, ct = call_info subentry = Subentry(entry.code, callcount=cc, reccallcount=nc - cc, inlinetime=tt, totaltime=ct) # entry_caller has the same form as code_info entries[entry_caller].calls.append(subentry) return list(entries.values())
def _output_entry(self, entry): out_file = self.out_file code = entry.code co_filename, co_firstlineno, co_name = cProfile.label(code) munged_name = self.munged_function_name(code) out_file.write('fl=%s\nfn=%s\n' % (co_filename, munged_name)) inlinetime = int(entry.inlinetime * SCALE) out_file.write('%d %d\n' % (co_firstlineno, inlinetime)) # recursive calls are counted in entry.calls if entry.calls: for subentry in sorted(entry.calls, key=_entry_sort_key): self._output_subentry(co_firstlineno, subentry.code, subentry.callcount, int(subentry.totaltime * SCALE)) out_file.write('\n')
def generate_stats(self, request, response): if not hasattr(self, "profiler"): return None # Could be delayed until the panel content is requested (perf. optim.) self.profiler.create_stats() self.stats = Stats(self.profiler) self.stats.calc_callees() root_func = cProfile.label(super().process_request.__code__) if root_func in self.stats.stats: root = FunctionCall(self.stats, root_func, depth=0) func_list = [] self.add_node( func_list, root, dt_settings.get_config()["PROFILER_MAX_DEPTH"], root.stats[3] / 8, ) self.record_stats({"func_list": func_list})
def entry_to_dict(stat, total_time=None, path_replace=None): code = stat.code if isinstance(code, str): code = Code(*cProfile.label(code)) path = code.co_filename for pattern, repl in (path_replace or {}).items(): path, _ = re.subn(pattern, repl, path) data = { "callcount": stat.callcount, "inlinetime": stat.inlinetime, "reccallcount": stat.reccallcount, "totaltime": stat.totaltime, "calls": len(stat.calls or []), "path": path, "lineno": code.co_firstlineno, "method": code.co_name, } if total_time is not None: data["percent"] = 100 * stat.totaltime / total_time return data
def pstats2entries(data): """Helper to convert serialized pstats back to a list of raw entries Converse opperation of cProfile.Profile.snapshot_stats() """ entries = dict() allcallers = dict() # first pass over stats to build the list of entry instances for code_info, call_info in data.stats.items(): # build a fake code object code = Code() code.co_filename, code.co_firstlineno, code.co_name = code_info # build a fake entry object cc, nc, tt, ct, callers = call_info entry = Entry() entry.code = code entry.callcount = cc entry.reccallcount = nc - cc entry.inlinetime = tt entry.totaltime = ct # to be filled during the second pass over stats entry.calls = list() # collect the new entry entries[code_info] = entry allcallers[code_info] = callers.items() # second pass of stats to plug callees into callers for entry in entries.itervalues(): entry_label = cProfile.label(entry.code) entry_callers = allcallers.get(entry_label, []) for entry_caller, call_info in entry_callers: entries[entry_caller].calls.append((entry, call_info)) return entries.values()
def pstats2entries(data): """Helper to convert serialized pstats back to a list of raw entries Converse operation of cProfile.Profile.snapshot_stats() """ entries = dict() allcallers = dict() # first pass over stats to build the list of entry instances for code_info, call_info in data.stats.items(): # build a fake code object code = Code() code.co_filename, code.co_firstlineno, code.co_name = code_info # build a fake entry object cc, nc, tt, ct, callers = call_info entry = Entry() entry.code = code entry.callcount = cc entry.reccallcount = nc - cc entry.inlinetime = tt entry.totaltime = ct # to be filled during the second pass over stats entry.calls = list() # collect the new entry entries[code_info] = entry allcallers[code_info] = callers.items() # second pass of stats to plug callees into callers for entry in entries.itervalues(): entry_label = cProfile.label(entry.code) entry_callers = allcallers.get(entry_label, []) for entry_caller, call_info in entry_callers: entries[entry_caller].calls.append((entry, call_info)) return entries.values()
def pstats2entries(data): """Helper to convert serialized pstats back to a list of raw entries. Converse operation of cProfile.Profile.snapshot_stats() """ # Each entry's key is a tuple of (filename, line number, function name) entries = {} allcallers = {} # first pass over stats to build the list of entry instances for code_info, call_info in data.stats.items(): # build a fake code object code = Code(*code_info) # build a fake entry object. entry.calls will be filled during the # second pass over stats cc, nc, tt, ct, callers = call_info entry = Entry(code, callcount=cc, reccallcount=nc - cc, inlinetime=tt, totaltime=ct, calls=[]) # collect the new entry entries[code_info] = entry allcallers[code_info] = list(callers.items()) # second pass of stats to plug callees into callers for entry in entries.values(): entry_label = cProfile.label(entry.code) entry_callers = allcallers.get(entry_label, []) for entry_caller, call_info in entry_callers: cc, nc, tt, ct = call_info subentry = Subentry(entry.code, callcount=cc, reccallcount=nc - cc, inlinetime=tt, totaltime=ct) # entry_caller has the same form as code_info entries[entry_caller].calls.append(subentry) return list(entries.values())
def _code_str(code): if isinstance(code, str): code = Code(*cProfile.label(code)) return f"{code.co_filename},{code.co_firstlineno},{code.co_name}"
def munged_function_name(self, code): co_filename, co_firstlineno, co_name = cProfile.label(code) if len(self._code_by_position[(co_filename, co_name)]) == 1: return co_name return "%s:%d" % (co_name, co_firstlineno)
def _add_code_by_position(self, code): co_filename, _, co_name = cProfile.label(code) self._code_by_position[(co_filename, co_name)].add(code)
def _entry_sort_key(entry): return cProfile.label(entry.code)
def unique_name(code): co_filename, co_firstlineno, co_name = cProfile.label(code) munged_name = converter.munged_function_name(code) return '%s::%s' % (co_filename, munged_name)
def pstats2entries(data): """Convert serialized pstats back to a list of raw entries. Converse operation of cProfile.Profile.snapshot_stats() Each profiler_entry is a tuple-like object with the following attributes: code code object callcount how many times this was called reccallcount how many times called recursively totaltime total time in this entry inlinetime inline time in this entry (not in subcalls) calls details of the calls The calls attribute is a list of profiler_subentry objects: code called code object callcount how many times this is called reccallcount how many times this is called recursively totaltime total time spent in this call inlinetime inline time (not in further subcalls) """ # Each entry's key is a tuple of (filename, line number, function name) entries = {} allcallers = {} # first pass over stats to build the list of entry instances for code_info, call_info in data.stats.items(): # build a fake code object code = Code(*code_info) # build a fake entry object. entry.calls will be filled during the # second pass over stats cc, nc, tt, ct, callers = call_info entry = Entry( code, callcount=cc, reccallcount=nc - cc, inlinetime=tt, totaltime=ct, calls=[], ) # collect the new entry entries[code_info] = entry allcallers[code_info] = list(callers.items()) # second pass of stats to plug callees into callers for entry in entries.values(): entry_label = cProfile.label(entry.code) entry_callers = allcallers.get(entry_label, []) for entry_caller, call_info in entry_callers: cc, nc, tt, ct = call_info subentry = Subentry( entry.code, callcount=cc, reccallcount=nc - cc, inlinetime=tt, totaltime=ct, ) # entry_caller has the same form as code_info entries[entry_caller].calls.append(subentry) return list(entries.values())