diff options
author | Fred Drake <fdrake@acm.org> | 2007-10-11 18:01:43 (GMT) |
---|---|---|
committer | Fred Drake <fdrake@acm.org> | 2007-10-11 18:01:43 (GMT) |
commit | 0e474a801ac6e01a24b900183ef101962148f317 (patch) | |
tree | 18376be3413a5cd6ebf2bf1a8d091022adf0d9aa /Lib/hotshot | |
parent | b62e8a8062ff81f0f5d80b25aa0fb6b2457c721c (diff) | |
download | cpython-0e474a801ac6e01a24b900183ef101962148f317.zip cpython-0e474a801ac6e01a24b900183ef101962148f317.tar.gz cpython-0e474a801ac6e01a24b900183ef101962148f317.tar.bz2 |
remove hotshot profiler from Py3k
Diffstat (limited to 'Lib/hotshot')
-rw-r--r-- | Lib/hotshot/__init__.py | 76 | ||||
-rw-r--r-- | Lib/hotshot/log.py | 192 | ||||
-rw-r--r-- | Lib/hotshot/stats.py | 93 | ||||
-rw-r--r-- | Lib/hotshot/stones.py | 31 |
4 files changed, 0 insertions, 392 deletions
diff --git a/Lib/hotshot/__init__.py b/Lib/hotshot/__init__.py deleted file mode 100644 index b9f7866..0000000 --- a/Lib/hotshot/__init__.py +++ /dev/null @@ -1,76 +0,0 @@ -"""High-perfomance logging profiler, mostly written in C.""" - -import _hotshot - -from _hotshot import ProfilerError - - -class Profile: - def __init__(self, logfn, lineevents=0, linetimings=1): - self.lineevents = lineevents and 1 or 0 - self.linetimings = (linetimings and lineevents) and 1 or 0 - self._prof = p = _hotshot.profiler( - logfn, self.lineevents, self.linetimings) - - # Attempt to avoid confusing results caused by the presence of - # Python wrappers around these functions, but only if we can - # be sure the methods have not been overridden or extended. - if self.__class__ is Profile: - self.close = p.close - self.start = p.start - self.stop = p.stop - self.addinfo = p.addinfo - - def close(self): - """Close the logfile and terminate the profiler.""" - self._prof.close() - - def fileno(self): - """Return the file descriptor of the profiler's log file.""" - return self._prof.fileno() - - def start(self): - """Start the profiler.""" - self._prof.start() - - def stop(self): - """Stop the profiler.""" - self._prof.stop() - - def addinfo(self, key, value): - """Add an arbitrary labelled value to the profile log.""" - self._prof.addinfo(key, value) - - # These methods offer the same interface as the profile.Profile class, - # but delegate most of the work to the C implementation underneath. - - def run(self, cmd): - """Profile an exec-compatible string in the script - environment. - - The globals from the __main__ module are used as both the - globals and locals for the script. - """ - import __main__ - dict = __main__.__dict__ - return self.runctx(cmd, dict, dict) - - def runctx(self, cmd, globals, locals): - """Evaluate an exec-compatible string in a specific - environment. - - The string is compiled before profiling begins. - """ - code = compile(cmd, "<string>", "exec") - self._prof.runcode(code, globals, locals) - return self - - def runcall(self, func, *args, **kw): - """Profile a single call of a callable. - - Additional positional and keyword arguments may be passed - along; the result of the call is returned, and exceptions are - allowed to propogate cleanly, while ensuring that profiling is - disabled on the way out. - """ - return self._prof.runcall(func, args, kw) diff --git a/Lib/hotshot/log.py b/Lib/hotshot/log.py deleted file mode 100644 index b211825..0000000 --- a/Lib/hotshot/log.py +++ /dev/null @@ -1,192 +0,0 @@ -import _hotshot -import os.path -import parser -import symbol -import sys - -from _hotshot import \ - WHAT_ENTER, \ - WHAT_EXIT, \ - WHAT_LINENO, \ - WHAT_DEFINE_FILE, \ - WHAT_DEFINE_FUNC, \ - WHAT_ADD_INFO - - -__all__ = ["LogReader", "ENTER", "EXIT", "LINE"] - - -ENTER = WHAT_ENTER -EXIT = WHAT_EXIT -LINE = WHAT_LINENO - - -class LogReader: - def __init__(self, logfn): - # fileno -> filename - self._filemap = {} - # (fileno, lineno) -> filename, funcname - self._funcmap = {} - - self._reader = _hotshot.logreader(logfn) - self._nextitem = self._reader.__next__ - self._info = self._reader.info - if 'current-directory' in self._info: - self.cwd = self._info['current-directory'] - else: - self.cwd = None - - # This mirrors the call stack of the profiled code as the log - # is read back in. It contains tuples of the form: - # - # (file name, line number of function def, function name) - # - self._stack = [] - self._append = self._stack.append - self._pop = self._stack.pop - - def close(self): - self._reader.close() - - def fileno(self): - """Return the file descriptor of the log reader's log file.""" - return self._reader.fileno() - - def addinfo(self, key, value): - """This method is called for each additional ADD_INFO record. - - This can be overridden by applications that want to receive - these events. The default implementation does not need to be - called by alternate implementations. - - The initial set of ADD_INFO records do not pass through this - mechanism; this is only needed to receive notification when - new values are added. Subclasses can inspect self._info after - calling LogReader.__init__(). - """ - pass - - def get_filename(self, fileno): - try: - return self._filemap[fileno] - except KeyError: - raise ValueError("unknown fileno") - - def get_filenames(self): - return self._filemap.values() - - def get_fileno(self, filename): - filename = os.path.normcase(os.path.normpath(filename)) - for fileno, name in self._filemap.items(): - if name == filename: - return fileno - raise ValueError("unknown filename") - - def get_funcname(self, fileno, lineno): - try: - return self._funcmap[(fileno, lineno)] - except KeyError: - raise ValueError("unknown function location") - - # Iteration support: - # This adds an optional (& ignored) parameter to next() so that the - # same bound method can be used as the __getitem__() method -- this - # avoids using an additional method call which kills the performance. - - def __next__(self, index=0): - while 1: - # This call may raise StopIteration: - what, tdelta, fileno, lineno = self._nextitem() - - # handle the most common cases first - - if what == WHAT_ENTER: - filename, funcname = self._decode_location(fileno, lineno) - t = (filename, lineno, funcname) - self._append(t) - return what, t, tdelta - - if what == WHAT_EXIT: - return what, self._pop(), tdelta - - if what == WHAT_LINENO: - filename, firstlineno, funcname = self._stack[-1] - return what, (filename, lineno, funcname), tdelta - - if what == WHAT_DEFINE_FILE: - filename = os.path.normcase(os.path.normpath(tdelta)) - self._filemap[fileno] = filename - elif what == WHAT_DEFINE_FUNC: - filename = self._filemap[fileno] - self._funcmap[(fileno, lineno)] = (filename, tdelta) - elif what == WHAT_ADD_INFO: - # value already loaded into self.info; call the - # overridable addinfo() handler so higher-level code - # can pick up the new value - if tdelta == 'current-directory': - self.cwd = lineno - self.addinfo(tdelta, lineno) - else: - raise ValueError("unknown event type") - - def __iter__(self): - return self - - # - # helpers - # - - def _decode_location(self, fileno, lineno): - try: - return self._funcmap[(fileno, lineno)] - except KeyError: - # - # This should only be needed when the log file does not - # contain all the DEFINE_FUNC records needed to allow the - # function name to be retrieved from the log file. - # - if self._loadfile(fileno): - filename = funcname = None - try: - filename, funcname = self._funcmap[(fileno, lineno)] - except KeyError: - filename = self._filemap.get(fileno) - funcname = None - self._funcmap[(fileno, lineno)] = (filename, funcname) - return filename, funcname - - def _loadfile(self, fileno): - try: - filename = self._filemap[fileno] - except KeyError: - print("Could not identify fileId", fileno) - return 1 - if filename is None: - return 1 - absname = os.path.normcase(os.path.join(self.cwd, filename)) - - try: - fp = open(absname) - except IOError: - return - st = parser.suite(fp.read()) - fp.close() - - # Scan the tree looking for def and lambda nodes, filling in - # self._funcmap with all the available information. - funcdef = symbol.funcdef - lambdef = symbol.lambdef - - stack = [st.totuple(1)] - - while stack: - tree = stack.pop() - try: - sym = tree[0] - except (IndexError, TypeError): - continue - if sym == funcdef: - self._funcmap[(fileno, tree[2][2])] = filename, tree[2][1] - elif sym == lambdef: - self._funcmap[(fileno, tree[1][2])] = filename, "<lambda>" - stack.extend(list(tree[1:])) diff --git a/Lib/hotshot/stats.py b/Lib/hotshot/stats.py deleted file mode 100644 index e927bd5..0000000 --- a/Lib/hotshot/stats.py +++ /dev/null @@ -1,93 +0,0 @@ -"""Statistics analyzer for HotShot.""" - -import profile -import pstats - -import hotshot.log - -from hotshot.log import ENTER, EXIT - - -def load(filename): - return StatsLoader(filename).load() - - -class StatsLoader: - def __init__(self, logfn): - self._logfn = logfn - self._code = {} - self._stack = [] - self.pop_frame = self._stack.pop - - def load(self): - # The timer selected by the profiler should never be used, so make - # sure it doesn't work: - p = Profile() - p.get_time = _brokentimer - log = hotshot.log.LogReader(self._logfn) - taccum = 0 - for event in log: - what, (filename, lineno, funcname), tdelta = event - if tdelta > 0: - taccum += tdelta - - # We multiply taccum to convert from the microseconds we - # have to the seconds that the profile/pstats module work - # with; this allows the numbers to have some basis in - # reality (ignoring calibration issues for now). - - if what == ENTER: - frame = self.new_frame(filename, lineno, funcname) - p.trace_dispatch_call(frame, taccum * .000001) - taccum = 0 - - elif what == EXIT: - frame = self.pop_frame() - p.trace_dispatch_return(frame, taccum * .000001) - taccum = 0 - - # no further work for line events - - assert not self._stack - return pstats.Stats(p) - - def new_frame(self, *args): - # args must be filename, firstlineno, funcname - # our code objects are cached since we don't need to create - # new ones every time - try: - code = self._code[args] - except KeyError: - code = FakeCode(*args) - self._code[args] = code - # frame objects are create fresh, since the back pointer will - # vary considerably - if self._stack: - back = self._stack[-1] - else: - back = None - frame = FakeFrame(code, back) - self._stack.append(frame) - return frame - - -class Profile(profile.Profile): - def simulate_cmd_complete(self): - pass - - -class FakeCode: - def __init__(self, filename, firstlineno, funcname): - self.co_filename = filename - self.co_firstlineno = firstlineno - self.co_name = self.__name__ = funcname - - -class FakeFrame: - def __init__(self, code, back): - self.f_back = back - self.f_code = code - - -def _brokentimer(): - raise RuntimeError("this timer should not be called") diff --git a/Lib/hotshot/stones.py b/Lib/hotshot/stones.py deleted file mode 100644 index 8f974b9..0000000 --- a/Lib/hotshot/stones.py +++ /dev/null @@ -1,31 +0,0 @@ -import errno -import hotshot -import hotshot.stats -import os -import sys -import test.pystone - -def main(logfile): - p = hotshot.Profile(logfile) - benchtime, stones = p.runcall(test.pystone.pystones) - p.close() - - print("Pystone(%s) time for %d passes = %g" % \ - (test.pystone.__version__, test.pystone.LOOPS, benchtime)) - print("This machine benchmarks at %g pystones/second" % stones) - - stats = hotshot.stats.load(logfile) - stats.strip_dirs() - stats.sort_stats('time', 'calls') - try: - stats.print_stats(20) - except IOError as e: - if e.errno != errno.EPIPE: - raise - -if __name__ == '__main__': - if sys.argv[1:]: - main(sys.argv[1]) - else: - import tempfile - main(tempfile.NamedTemporaryFile().name) |