You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
232 lines
8.0 KiB
Plaintext
232 lines
8.0 KiB
Plaintext
###########################################################################
|
|
#
|
|
# Psyco main functions.
|
|
# Copyright (C) 2001-2002 Armin Rigo et.al.
|
|
|
|
"""Psyco main functions.
|
|
|
|
Here are the routines that you can use from your applications.
|
|
These are mostly interfaces to the C core, but they depend on
|
|
the Python version.
|
|
|
|
You can use these functions from the 'psyco' module instead of
|
|
'psyco.core', e.g.
|
|
|
|
import psyco
|
|
psyco.log('/tmp/psyco.log')
|
|
psyco.profile()
|
|
"""
|
|
###########################################################################
|
|
|
|
import _psyco
|
|
import types
|
|
from support import *
|
|
|
|
newfunction = types.FunctionType
|
|
newinstancemethod = types.MethodType
|
|
|
|
|
|
# Default charge profiler values
|
|
default_watermark = 0.09 # between 0.0 (0%) and 1.0 (100%)
|
|
default_halflife = 0.5 # seconds
|
|
default_pollfreq_profile = 20 # Hz
|
|
default_pollfreq_background = 100 # Hz -- a maximum for sleep's resolution
|
|
default_parentframe = 0.25 # should not be more than 0.5 (50%)
|
|
|
|
|
|
def full(memory=None, time=None, memorymax=None, timemax=None):
|
|
"""Compile as much as possible.
|
|
|
|
Typical use is for small scripts performing intensive computations
|
|
or string handling."""
|
|
import profiler
|
|
p = profiler.FullCompiler()
|
|
p.run(memory, time, memorymax, timemax)
|
|
|
|
|
|
def profile(watermark = default_watermark,
|
|
halflife = default_halflife,
|
|
pollfreq = default_pollfreq_profile,
|
|
parentframe = default_parentframe,
|
|
memory=None, time=None, memorymax=None, timemax=None):
|
|
"""Turn on profiling.
|
|
|
|
The 'watermark' parameter controls how easily running functions will
|
|
be compiled. The smaller the value, the more functions are compiled."""
|
|
import profiler
|
|
p = profiler.ActivePassiveProfiler(watermark, halflife,
|
|
pollfreq, parentframe)
|
|
p.run(memory, time, memorymax, timemax)
|
|
|
|
|
|
def background(watermark = default_watermark,
|
|
halflife = default_halflife,
|
|
pollfreq = default_pollfreq_background,
|
|
parentframe = default_parentframe,
|
|
memory=None, time=None, memorymax=None, timemax=None):
|
|
"""Turn on passive profiling.
|
|
|
|
This is a very lightweight mode in which only intensively computing
|
|
functions can be detected. The smaller the 'watermark', the more functions
|
|
are compiled."""
|
|
import profiler
|
|
p = profiler.PassiveProfiler(watermark, halflife, pollfreq, parentframe)
|
|
p.run(memory, time, memorymax, timemax)
|
|
|
|
|
|
def runonly(memory=None, time=None, memorymax=None, timemax=None):
|
|
"""Nonprofiler.
|
|
|
|
XXX check if this is useful and document."""
|
|
import profiler
|
|
p = profiler.RunOnly()
|
|
p.run(memory, time, memorymax, timemax)
|
|
|
|
|
|
def stop():
|
|
"""Turn off all automatic compilation. bind() calls remain in effect."""
|
|
import profiler
|
|
profiler.go([])
|
|
|
|
|
|
def log(logfile='', mode='w', top=10):
|
|
"""Enable logging to the given file.
|
|
|
|
If the file name is unspecified, a default name is built by appending
|
|
a 'log-psyco' extension to the main script name.
|
|
|
|
Mode is 'a' to append to a possibly existing file or 'w' to overwrite
|
|
an existing file. Note that the log file may grow quickly in 'a' mode."""
|
|
import profiler, logger
|
|
if not logfile:
|
|
import os
|
|
logfile, dummy = os.path.splitext(sys.argv[0])
|
|
if os.path.basename(logfile):
|
|
logfile += '.'
|
|
logfile += 'log-psyco'
|
|
if hasattr(_psyco, 'VERBOSE_LEVEL'):
|
|
print >> sys.stderr, 'psyco: logging to', logfile
|
|
# logger.current should be a real file object; subtle problems
|
|
# will show up if its write() and flush() methods are written
|
|
# in Python, as Psyco will invoke them while compiling.
|
|
logger.current = open(logfile, mode)
|
|
logger.print_charges = top
|
|
profiler.logger = logger
|
|
logger.writedate('Logging started')
|
|
cannotcompile(logger.psycowrite)
|
|
_psyco.statwrite(logger=logger.psycowrite)
|
|
|
|
|
|
def bind(x, rec=None):
|
|
"""Enable compilation of the given function, method, or class object.
|
|
|
|
If C is a class (or anything with a '__dict__' attribute), bind(C) will
|
|
rebind all functions and methods found in C.__dict__ (which means, for
|
|
classes, all methods defined in the class but not in its parents).
|
|
|
|
The optional second argument specifies the number of recursive
|
|
compilation levels: all functions called by func are compiled
|
|
up to the given depth of indirection."""
|
|
if isinstance(x, types.MethodType):
|
|
x = x.im_func
|
|
if isinstance(x, types.FunctionType):
|
|
if rec is None:
|
|
x.func_code = _psyco.proxycode(x)
|
|
else:
|
|
x.func_code = _psyco.proxycode(x, rec)
|
|
return
|
|
if hasattr(x, '__dict__'):
|
|
funcs = [o for o in x.__dict__.values()
|
|
if isinstance(o, types.MethodType)
|
|
or isinstance(o, types.FunctionType)]
|
|
if not funcs:
|
|
raise error, ("nothing bindable found in %s object" %
|
|
type(x).__name__)
|
|
for o in funcs:
|
|
bind(o, rec)
|
|
return
|
|
raise TypeError, "cannot bind %s objects" % type(x).__name__
|
|
|
|
|
|
def unbind(x):
|
|
"""Reverse of bind()."""
|
|
if isinstance(x, types.MethodType):
|
|
x = x.im_func
|
|
if isinstance(x, types.FunctionType):
|
|
try:
|
|
f = _psyco.unproxycode(x.func_code)
|
|
except error:
|
|
pass
|
|
else:
|
|
x.func_code = f.func_code
|
|
return
|
|
if hasattr(x, '__dict__'):
|
|
for o in x.__dict__.values():
|
|
if (isinstance(o, types.MethodType)
|
|
or isinstance(o, types.FunctionType)):
|
|
unbind(o)
|
|
return
|
|
raise TypeError, "cannot unbind %s objects" % type(x).__name__
|
|
|
|
|
|
def proxy(x, rec=None):
|
|
"""Return a Psyco-enabled copy of the function.
|
|
|
|
The original function is still available for non-compiled calls.
|
|
The optional second argument specifies the number of recursive
|
|
compilation levels: all functions called by func are compiled
|
|
up to the given depth of indirection."""
|
|
if isinstance(x, types.FunctionType):
|
|
if rec is None:
|
|
code = _psyco.proxycode(x)
|
|
else:
|
|
code = _psyco.proxycode(x, rec)
|
|
return newfunction(code, x.func_globals, x.func_name)
|
|
if isinstance(x, types.MethodType):
|
|
p = proxy(x.im_func, rec)
|
|
return newinstancemethod(p, x.im_self, x.im_class)
|
|
raise TypeError, "cannot proxy %s objects" % type(x).__name__
|
|
|
|
|
|
def unproxy(proxy):
|
|
"""Return a new copy of the original function of method behind a proxy.
|
|
The result behaves like the original function in that calling it
|
|
does not trigger compilation nor execution of any compiled code."""
|
|
if isinstance(proxy, types.FunctionType):
|
|
return _psyco.unproxycode(proxy.func_code)
|
|
if isinstance(proxy, types.MethodType):
|
|
f = unproxy(proxy.im_func)
|
|
return newinstancemethod(f, proxy.im_self, proxy.im_class)
|
|
raise TypeError, "%s objects cannot be proxies" % type(proxy).__name__
|
|
|
|
|
|
def cannotcompile(x):
|
|
"""Instruct Psyco never to compile the given function, method
|
|
or code object."""
|
|
if isinstance(x, types.MethodType):
|
|
x = x.im_func
|
|
if isinstance(x, types.FunctionType):
|
|
x = x.func_code
|
|
if isinstance(x, types.CodeType):
|
|
_psyco.cannotcompile(x)
|
|
else:
|
|
raise TypeError, "unexpected %s object" % type(x).__name__
|
|
|
|
|
|
def dumpcodebuf():
|
|
"""Write in file psyco.dump a copy of the emitted machine code,
|
|
provided Psyco was compiled with a non-zero CODE_DUMP.
|
|
See py-utils/httpxam.py to examine psyco.dump."""
|
|
if hasattr(_psyco, 'dumpcodebuf'):
|
|
_psyco.dumpcodebuf()
|
|
|
|
|
|
###########################################################################
|
|
# Psyco variables
|
|
# error * the error raised by Psyco
|
|
# warning * the warning raised by Psyco
|
|
# __in_psyco__ * a new built-in variable which is always zero, but which
|
|
# Psyco special-cases by returning 1 instead. So
|
|
# __in_psyco__ can be used in a function to know if
|
|
# that function is being executed by Psyco or not.
|