summaryrefslogtreecommitdiffstats
path: root/Lib/hotshot
diff options
context:
space:
mode:
authorFred Drake <fdrake@acm.org>2007-10-11 18:01:43 (GMT)
committerFred Drake <fdrake@acm.org>2007-10-11 18:01:43 (GMT)
commit0e474a801ac6e01a24b900183ef101962148f317 (patch)
tree18376be3413a5cd6ebf2bf1a8d091022adf0d9aa /Lib/hotshot
parentb62e8a8062ff81f0f5d80b25aa0fb6b2457c721c (diff)
downloadcpython-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__.py76
-rw-r--r--Lib/hotshot/log.py192
-rw-r--r--Lib/hotshot/stats.py93
-rw-r--r--Lib/hotshot/stones.py31
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)