1f019324b5c7a77f4983c06e5abb03b7751ea7305Fred Drake"""High-perfomance logging profiler, mostly written in C."""
2f019324b5c7a77f4983c06e5abb03b7751ea7305Fred Drake
3f019324b5c7a77f4983c06e5abb03b7751ea7305Fred Drakeimport _hotshot
4f019324b5c7a77f4983c06e5abb03b7751ea7305Fred Drakefrom _hotshot import ProfilerError
5f019324b5c7a77f4983c06e5abb03b7751ea7305Fred Drake
6ab68a3dc6fbf0dd9e1737516aa9bf75485842cdeAlexandre Vassalottifrom warnings import warnpy3k as _warnpy3k
7ab68a3dc6fbf0dd9e1737516aa9bf75485842cdeAlexandre Vassalotti_warnpy3k("The 'hotshot' module is not supported in 3.x, "
8ab68a3dc6fbf0dd9e1737516aa9bf75485842cdeAlexandre Vassalotti          "use the 'profile' module instead.", stacklevel=2)
9f019324b5c7a77f4983c06e5abb03b7751ea7305Fred Drake
10f019324b5c7a77f4983c06e5abb03b7751ea7305Fred Drakeclass Profile:
11f019324b5c7a77f4983c06e5abb03b7751ea7305Fred Drake    def __init__(self, logfn, lineevents=0, linetimings=1):
12f019324b5c7a77f4983c06e5abb03b7751ea7305Fred Drake        self.lineevents = lineevents and 1 or 0
13f019324b5c7a77f4983c06e5abb03b7751ea7305Fred Drake        self.linetimings = (linetimings and lineevents) and 1 or 0
14f019324b5c7a77f4983c06e5abb03b7751ea7305Fred Drake        self._prof = p = _hotshot.profiler(
15f019324b5c7a77f4983c06e5abb03b7751ea7305Fred Drake            logfn, self.lineevents, self.linetimings)
16f019324b5c7a77f4983c06e5abb03b7751ea7305Fred Drake
1734f300a53ea4e5a8396129b171e6d97bf4e4680dFred Drake        # Attempt to avoid confusing results caused by the presence of
1834f300a53ea4e5a8396129b171e6d97bf4e4680dFred Drake        # Python wrappers around these functions, but only if we can
1934f300a53ea4e5a8396129b171e6d97bf4e4680dFred Drake        # be sure the methods have not been overridden or extended.
2034f300a53ea4e5a8396129b171e6d97bf4e4680dFred Drake        if self.__class__ is Profile:
2134f300a53ea4e5a8396129b171e6d97bf4e4680dFred Drake            self.close = p.close
2234f300a53ea4e5a8396129b171e6d97bf4e4680dFred Drake            self.start = p.start
2334f300a53ea4e5a8396129b171e6d97bf4e4680dFred Drake            self.stop = p.stop
2434f300a53ea4e5a8396129b171e6d97bf4e4680dFred Drake            self.addinfo = p.addinfo
2534f300a53ea4e5a8396129b171e6d97bf4e4680dFred Drake
26f019324b5c7a77f4983c06e5abb03b7751ea7305Fred Drake    def close(self):
2734f300a53ea4e5a8396129b171e6d97bf4e4680dFred Drake        """Close the logfile and terminate the profiler."""
28f019324b5c7a77f4983c06e5abb03b7751ea7305Fred Drake        self._prof.close()
29f019324b5c7a77f4983c06e5abb03b7751ea7305Fred Drake
30302e2bb81b462f2664b71da9f35c2969df8a330eFred Drake    def fileno(self):
31302e2bb81b462f2664b71da9f35c2969df8a330eFred Drake        """Return the file descriptor of the profiler's log file."""
32302e2bb81b462f2664b71da9f35c2969df8a330eFred Drake        return self._prof.fileno()
33302e2bb81b462f2664b71da9f35c2969df8a330eFred Drake
34f019324b5c7a77f4983c06e5abb03b7751ea7305Fred Drake    def start(self):
3534f300a53ea4e5a8396129b171e6d97bf4e4680dFred Drake        """Start the profiler."""
36f019324b5c7a77f4983c06e5abb03b7751ea7305Fred Drake        self._prof.start()
37f019324b5c7a77f4983c06e5abb03b7751ea7305Fred Drake
38f019324b5c7a77f4983c06e5abb03b7751ea7305Fred Drake    def stop(self):
3934f300a53ea4e5a8396129b171e6d97bf4e4680dFred Drake        """Stop the profiler."""
40f019324b5c7a77f4983c06e5abb03b7751ea7305Fred Drake        self._prof.stop()
41f019324b5c7a77f4983c06e5abb03b7751ea7305Fred Drake
42165b2cc2bdf17b1cb4b695f2438e611313d99c1cFred Drake    def addinfo(self, key, value):
4334f300a53ea4e5a8396129b171e6d97bf4e4680dFred Drake        """Add an arbitrary labelled value to the profile log."""
44165b2cc2bdf17b1cb4b695f2438e611313d99c1cFred Drake        self._prof.addinfo(key, value)
45165b2cc2bdf17b1cb4b695f2438e611313d99c1cFred Drake
46f019324b5c7a77f4983c06e5abb03b7751ea7305Fred Drake    # These methods offer the same interface as the profile.Profile class,
47f019324b5c7a77f4983c06e5abb03b7751ea7305Fred Drake    # but delegate most of the work to the C implementation underneath.
48f019324b5c7a77f4983c06e5abb03b7751ea7305Fred Drake
49f019324b5c7a77f4983c06e5abb03b7751ea7305Fred Drake    def run(self, cmd):
5034f300a53ea4e5a8396129b171e6d97bf4e4680dFred Drake        """Profile an exec-compatible string in the script
5134f300a53ea4e5a8396129b171e6d97bf4e4680dFred Drake        environment.
5234f300a53ea4e5a8396129b171e6d97bf4e4680dFred Drake
5334f300a53ea4e5a8396129b171e6d97bf4e4680dFred Drake        The globals from the __main__ module are used as both the
5434f300a53ea4e5a8396129b171e6d97bf4e4680dFred Drake        globals and locals for the script.
5534f300a53ea4e5a8396129b171e6d97bf4e4680dFred Drake        """
56f019324b5c7a77f4983c06e5abb03b7751ea7305Fred Drake        import __main__
57f019324b5c7a77f4983c06e5abb03b7751ea7305Fred Drake        dict = __main__.__dict__
58f019324b5c7a77f4983c06e5abb03b7751ea7305Fred Drake        return self.runctx(cmd, dict, dict)
59f019324b5c7a77f4983c06e5abb03b7751ea7305Fred Drake
60f019324b5c7a77f4983c06e5abb03b7751ea7305Fred Drake    def runctx(self, cmd, globals, locals):
6134f300a53ea4e5a8396129b171e6d97bf4e4680dFred Drake        """Evaluate an exec-compatible string in a specific
6234f300a53ea4e5a8396129b171e6d97bf4e4680dFred Drake        environment.
6334f300a53ea4e5a8396129b171e6d97bf4e4680dFred Drake
6434f300a53ea4e5a8396129b171e6d97bf4e4680dFred Drake        The string is compiled before profiling begins.
6534f300a53ea4e5a8396129b171e6d97bf4e4680dFred Drake        """
66f019324b5c7a77f4983c06e5abb03b7751ea7305Fred Drake        code = compile(cmd, "<string>", "exec")
67f019324b5c7a77f4983c06e5abb03b7751ea7305Fred Drake        self._prof.runcode(code, globals, locals)
68f019324b5c7a77f4983c06e5abb03b7751ea7305Fred Drake        return self
69f019324b5c7a77f4983c06e5abb03b7751ea7305Fred Drake
70f019324b5c7a77f4983c06e5abb03b7751ea7305Fred Drake    def runcall(self, func, *args, **kw):
7134f300a53ea4e5a8396129b171e6d97bf4e4680dFred Drake        """Profile a single call of a callable.
7234f300a53ea4e5a8396129b171e6d97bf4e4680dFred Drake
7334f300a53ea4e5a8396129b171e6d97bf4e4680dFred Drake        Additional positional and keyword arguments may be passed
7434f300a53ea4e5a8396129b171e6d97bf4e4680dFred Drake        along; the result of the call is returned, and exceptions are
758d496add74530767cad3aa8b5b371b9a7f0b8498Martin Panter        allowed to propagate cleanly, while ensuring that profiling is
7634f300a53ea4e5a8396129b171e6d97bf4e4680dFred Drake        disabled on the way out.
7734f300a53ea4e5a8396129b171e6d97bf4e4680dFred Drake        """
78e7d8a78b8e6d60d3d75f9dc0599288d0101fff05Fred Drake        return self._prof.runcall(func, args, kw)
79