buildframework/helium/external/python/lib/common/psyco-1.6-py2.5.egg/psyco/profiler.py
author wbernard
Wed, 23 Dec 2009 19:29:07 +0200
changeset 179 d8ac696cc51f
permissions -rw-r--r--
helium_7.0-r14027
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
179
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     1
###########################################################################
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     2
# 
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     3
#  Psyco profiler (Python part).
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     4
#   Copyright (C) 2001-2002  Armin Rigo et.al.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     5
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     6
"""Psyco profiler (Python part).
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     7
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     8
The implementation of the non-time-critical parts of the profiler.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     9
See profile() and full() in core.py for the easy interface.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    10
"""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    11
###########################################################################
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    12
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    13
import _psyco
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    14
from support import *
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    15
import math, time, types, atexit
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    16
now = time.time
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    17
try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    18
    import thread
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    19
except ImportError:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    20
    import dummy_thread as thread
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    21
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    22
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    23
# current profiler instance
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    24
current = None
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    25
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    26
# enabled profilers, in order of priority
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    27
profilers = []
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    28
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    29
# logger module (when enabled by core.log())
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    30
logger = None
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    31
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    32
# a lock for a thread-safe go()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    33
go_lock = thread.allocate_lock()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    34
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    35
def go(stop=0):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    36
    # run the highest-priority profiler in 'profilers'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    37
    global current
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    38
    go_lock.acquire()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    39
    try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    40
        prev = current
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    41
        if stop:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    42
            del profilers[:]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    43
        if prev:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    44
            if profilers and profilers[0] is prev:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    45
                return    # best profiler already running
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    46
            prev.stop()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    47
            current = None
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    48
        for p in profilers[:]:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    49
            if p.start():
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    50
                current = p
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    51
                if logger: # and p is not prev:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    52
                    logger.write("%s: starting" % p.__class__.__name__, 5)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    53
                return
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    54
    finally:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    55
        go_lock.release()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    56
    # no profiler is running now
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    57
    if stop:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    58
        if logger:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    59
            logger.writefinalstats()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    60
    else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    61
        tag2bind()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    62
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    63
atexit.register(go, 1)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    64
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    65
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    66
def buildfncache(globals, cache):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    67
    if hasattr(types.IntType, '__dict__'):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    68
        clstypes = (types.ClassType, types.TypeType)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    69
    else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    70
        clstypes = types.ClassType
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    71
    for x in globals.values():
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    72
        if isinstance(x, types.MethodType):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    73
            x = x.im_func
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    74
        if isinstance(x, types.FunctionType):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    75
            cache[x.func_code] = x, ''
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    76
        elif isinstance(x, clstypes):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    77
            for y in x.__dict__.values():
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    78
                if isinstance(y, types.MethodType):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    79
                    y = y.im_func
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    80
                if isinstance(y, types.FunctionType):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    81
                    cache[y.func_code] = y, x.__name__
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    82
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    83
# code-to-function mapping (cache)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    84
function_cache = {}
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    85
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    86
def trytobind(co, globals, log=1):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    87
    try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    88
        f, clsname = function_cache[co]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    89
    except KeyError:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    90
        buildfncache(globals, function_cache)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    91
        try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    92
            f, clsname = function_cache[co]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    93
        except KeyError:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    94
            if logger:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    95
                logger.write('warning: cannot find function %s in %s' %
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    96
                             (co.co_name, globals.get('__name__', '?')), 3)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    97
            return  # give up
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    98
    if logger and log:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    99
        modulename = globals.get('__name__', '?')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   100
        if clsname:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   101
            modulename += '.' + clsname
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   102
        logger.write('bind function: %s.%s' % (modulename, co.co_name), 1)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   103
    f.func_code = _psyco.proxycode(f)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   104
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   105
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   106
# the list of code objects that have been tagged
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   107
tagged_codes = []
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   108
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   109
def tag(co, globals):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   110
    if logger:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   111
        try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   112
            f, clsname = function_cache[co]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   113
        except KeyError:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   114
            buildfncache(globals, function_cache)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   115
            try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   116
                f, clsname = function_cache[co]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   117
            except KeyError:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   118
                clsname = ''  # give up
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   119
        modulename = globals.get('__name__', '?')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   120
        if clsname:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   121
            modulename += '.' + clsname
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   122
        logger.write('tag function: %s.%s' % (modulename, co.co_name), 1)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   123
    tagged_codes.append((co, globals))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   124
    _psyco.turbo_frame(co)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   125
    _psyco.turbo_code(co)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   126
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   127
def tag2bind():
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   128
    if tagged_codes:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   129
        if logger:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   130
            logger.write('profiling stopped, binding %d functions' %
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   131
                         len(tagged_codes), 2)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   132
        for co, globals in tagged_codes:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   133
            trytobind(co, globals, 0)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   134
        function_cache.clear()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   135
        del tagged_codes[:]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   136
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   137
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   138
class Profiler:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   139
    MemoryTimerResolution = 0.103
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   140
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   141
    def run(self, memory, time, memorymax, timemax):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   142
        self.memory = memory
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   143
        self.memorymax = memorymax
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   144
        self.time = time
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   145
        if timemax is None:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   146
            self.endtime = None
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   147
        else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   148
            self.endtime = now() + timemax
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   149
        self.alarms = []
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   150
        profilers.append(self)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   151
        go()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   152
    
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   153
    def start(self):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   154
        curmem = _psyco.memory()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   155
        memlimits = []
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   156
        if self.memorymax is not None:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   157
            if curmem >= self.memorymax:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   158
                if logger:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   159
                    logger.writememory()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   160
                return self.limitreached('memorymax')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   161
            memlimits.append(self.memorymax)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   162
        if self.memory is not None:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   163
            if self.memory <= 0:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   164
                if logger:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   165
                    logger.writememory()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   166
                return self.limitreached('memory')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   167
            memlimits.append(curmem + self.memory)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   168
            self.memory_at_start = curmem
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   169
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   170
        curtime = now()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   171
        timelimits = []
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   172
        if self.endtime is not None:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   173
            if curtime >= self.endtime:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   174
                return self.limitreached('timemax')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   175
            timelimits.append(self.endtime - curtime)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   176
        if self.time is not None:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   177
            if self.time <= 0.0:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   178
                return self.limitreached('time')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   179
            timelimits.append(self.time)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   180
            self.time_at_start = curtime
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   181
        
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   182
        try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   183
            self.do_start()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   184
        except error, e:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   185
            if logger:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   186
                logger.write('%s: disabled by psyco.error:' % (
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   187
                    self.__class__.__name__), 4)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   188
                logger.write('    %s' % str(e), 3)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   189
            return 0
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   190
        
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   191
        if memlimits:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   192
            self.memlimits_args = (time.sleep, (self.MemoryTimerResolution,),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   193
                                   self.check_memory, (min(memlimits),))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   194
            self.alarms.append(_psyco.alarm(*self.memlimits_args))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   195
        if timelimits:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   196
            self.alarms.append(_psyco.alarm(time.sleep, (min(timelimits),),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   197
                                            self.time_out))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   198
        return 1
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   199
    
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   200
    def stop(self):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   201
        for alarm in self.alarms:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   202
            alarm.stop(0)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   203
        for alarm in self.alarms:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   204
            alarm.stop(1)   # wait for parallel threads to stop
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   205
        del self.alarms[:]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   206
        if self.time is not None:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   207
            self.time -= now() - self.time_at_start
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   208
        if self.memory is not None:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   209
            self.memory -= _psyco.memory() - self.memory_at_start
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   210
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   211
        try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   212
            self.do_stop()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   213
        except error:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   214
            return 0
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   215
        return 1
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   216
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   217
    def check_memory(self, limit):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   218
        if _psyco.memory() < limit:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   219
            return self.memlimits_args
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   220
        go()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   221
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   222
    def time_out(self):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   223
        self.time = 0.0
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   224
        go()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   225
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   226
    def limitreached(self, limitname):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   227
        try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   228
            profilers.remove(self)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   229
        except ValueError:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   230
            pass
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   231
        if logger:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   232
            logger.write('%s: disabled (%s limit reached)' % (
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   233
                self.__class__.__name__, limitname), 4)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   234
        return 0
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   235
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   236
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   237
class FullCompiler(Profiler):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   238
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   239
    def do_start(self):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   240
        _psyco.profiling('f')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   241
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   242
    def do_stop(self):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   243
        _psyco.profiling('.')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   244
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   245
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   246
class RunOnly(Profiler):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   247
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   248
    def do_start(self):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   249
        _psyco.profiling('n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   250
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   251
    def do_stop(self):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   252
        _psyco.profiling('.')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   253
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   254
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   255
class ChargeProfiler(Profiler):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   256
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   257
    def __init__(self, watermark, parentframe):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   258
        self.watermark = watermark
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   259
        self.parent2 = parentframe * 2.0
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   260
        self.lock = thread.allocate_lock()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   261
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   262
    def init_charges(self):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   263
        _psyco.statwrite(watermark = self.watermark,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   264
                         parent2   = self.parent2)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   265
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   266
    def do_stop(self):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   267
        _psyco.profiling('.')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   268
        _psyco.statwrite(callback = None)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   269
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   270
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   271
class ActiveProfiler(ChargeProfiler):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   272
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   273
    def active_start(self):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   274
        _psyco.profiling('p')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   275
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   276
    def do_start(self):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   277
        self.init_charges()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   278
        self.active_start()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   279
        _psyco.statwrite(callback = self.charge_callback)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   280
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   281
    def charge_callback(self, frame, charge):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   282
        tag(frame.f_code, frame.f_globals)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   283
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   284
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   285
class PassiveProfiler(ChargeProfiler):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   286
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   287
    initial_charge_unit   = _psyco.statread('unit')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   288
    reset_stats_after     = 120      # half-lives (maximum 200!)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   289
    reset_limit           = initial_charge_unit * (2.0 ** reset_stats_after)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   290
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   291
    def __init__(self, watermark, halflife, pollfreq, parentframe):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   292
        ChargeProfiler.__init__(self, watermark, parentframe)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   293
        self.pollfreq = pollfreq
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   294
        # self.progress is slightly more than 1.0, and computed so that
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   295
        # do_profile() will double the change_unit every 'halflife' seconds.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   296
        self.progress = 2.0 ** (1.0 / (halflife * pollfreq))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   297
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   298
    def reset(self):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   299
        _psyco.statwrite(unit = self.initial_charge_unit, callback = None)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   300
        _psyco.statreset()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   301
        if logger:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   302
            logger.write("%s: resetting stats" % self.__class__.__name__, 1)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   303
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   304
    def passive_start(self):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   305
        self.passivealarm_args = (time.sleep, (1.0 / self.pollfreq,),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   306
                                  self.do_profile)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   307
        self.alarms.append(_psyco.alarm(*self.passivealarm_args))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   308
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   309
    def do_start(self):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   310
        tag2bind()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   311
        self.init_charges()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   312
        self.passive_start()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   313
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   314
    def do_profile(self):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   315
        _psyco.statcollect()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   316
        if logger:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   317
            logger.dumpcharges()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   318
        nunit = _psyco.statread('unit') * self.progress
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   319
        if nunit > self.reset_limit:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   320
            self.reset()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   321
        else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   322
            _psyco.statwrite(unit = nunit, callback = self.charge_callback)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   323
        return self.passivealarm_args
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   324
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   325
    def charge_callback(self, frame, charge):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   326
        trytobind(frame.f_code, frame.f_globals)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   327
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   328
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   329
class ActivePassiveProfiler(PassiveProfiler, ActiveProfiler):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   330
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   331
    def do_start(self):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   332
        self.init_charges()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   333
        self.active_start()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   334
        self.passive_start()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   335
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   336
    def charge_callback(self, frame, charge):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   337
        tag(frame.f_code, frame.f_globals)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   338
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   339
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   340
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   341
#
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   342
# we register our own version of sys.settrace(), sys.setprofile()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   343
# and thread.start_new_thread().
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   344
#
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   345
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   346
def psyco_settrace(*args, **kw):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   347
    "This is the Psyco-aware version of sys.settrace()."
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   348
    result = original_settrace(*args, **kw)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   349
    go()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   350
    return result
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   351
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   352
def psyco_setprofile(*args, **kw):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   353
    "This is the Psyco-aware version of sys.setprofile()."
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   354
    result = original_setprofile(*args, **kw)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   355
    go()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   356
    return result
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   357
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   358
def psyco_thread_stub(callable, args, kw):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   359
    _psyco.statcollect()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   360
    if kw is None:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   361
        return callable(*args)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   362
    else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   363
        return callable(*args, **kw)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   364
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   365
def psyco_start_new_thread(callable, args, kw=None):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   366
    "This is the Psyco-aware version of thread.start_new_thread()."
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   367
    return original_start_new_thread(psyco_thread_stub, (callable, args, kw))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   368
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   369
original_settrace         = sys.settrace
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   370
original_setprofile       = sys.setprofile
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   371
original_start_new_thread = thread.start_new_thread
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   372
sys.settrace            = psyco_settrace
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   373
sys.setprofile          = psyco_setprofile
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   374
thread.start_new_thread = psyco_start_new_thread
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   375
# hack to patch threading._start_new_thread if the module is
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   376
# already loaded
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   377
if (sys.modules.has_key('threading') and
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   378
    hasattr(sys.modules['threading'], '_start_new_thread')):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   379
    sys.modules['threading']._start_new_thread = psyco_start_new_thread