/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to profile_imports.py

  • Committer: Robert Collins
  • Date: 2005-10-16 22:31:25 UTC
  • mto: This revision was merged to the branch mainline in revision 1458.
  • Revision ID: robertc@lifelesslap.robertcollins.net-20051016223125-26d4401cb94b7b82
Branch.relpath has been moved to WorkingTree.relpath.

WorkingTree no no longer takes an inventory, rather it takes an optional branch
parameter, and if None is given will open the branch at basedir implicitly.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006, 2008, 2009, 2010 by Canonical Ltd
2
 
# Written by John Arbash Meinel <john@arbash-meinel.com>
3
 
#
4
 
# This program is free software; you can redistribute it and/or modify
5
 
# it under the terms of the GNU General Public License as published by
6
 
# the Free Software Foundation; either version 2 of the License, or
7
 
# (at your option) any later version.
8
 
#
9
 
# This program is distributed in the hope that it will be useful,
10
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 
# GNU General Public License for more details.
13
 
#
14
 
# You should have received a copy of the GNU General Public License
15
 
# along with this program; if not, write to the Free Software
16
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
 
 
18
 
"""A custom importer and regex compiler which logs time spent."""
19
 
 
20
 
import sys
21
 
import time
22
 
 
23
 
 
24
 
if sys.version_info < (2, 5, 0):
25
 
    import sre
26
 
    re = sre
27
 
else:
28
 
    import re
29
 
 
30
 
 
31
 
_parent_stack = []
32
 
_total_stack = {}
33
 
_info = {}
34
 
_cur_id = 0
35
 
_timer = time.time
36
 
if sys.platform == 'win32':
37
 
    _timer = time.clock
38
 
 
39
 
 
40
 
def stack_add(name, frame_name, frame_lineno, scope_name=None):
41
 
    """Start a new record on the stack"""
42
 
    global _cur_id
43
 
    _cur_id += 1
44
 
    this_stack = (_cur_id, name)
45
 
 
46
 
    if _parent_stack:
47
 
        _total_stack[_parent_stack[-1]].append(this_stack)
48
 
    _total_stack[this_stack] = []
49
 
    _parent_stack.append(this_stack)
50
 
    _info[this_stack] = [len(_parent_stack)-1, frame_name, frame_lineno, scope_name]
51
 
 
52
 
    return this_stack
53
 
 
54
 
 
55
 
def stack_finish(this, cost):
56
 
    """Finish a given entry, and record its cost in time"""
57
 
    global _parent_stack
58
 
 
59
 
    assert _parent_stack[-1] == this, \
60
 
        'import stack does not end with this %s: %s' % (this, _parent_stack)
61
 
    _parent_stack.pop()
62
 
    _info[this].append(cost)
63
 
 
64
 
 
65
 
def log_stack_info(out_file, sorted=True, hide_fast=True):
66
 
    # Find all of the roots with import = 0
67
 
    out_file.write('%5s %5s %-40s @ %s:%s\n'
68
 
        % ('cum', 'inline', 'name', 'file', 'line'))
69
 
    todo = [(value[-1], key) for key,value in _info.iteritems() if value[0] == 0]
70
 
 
71
 
    if sorted:
72
 
        todo.sort()
73
 
 
74
 
    while todo:
75
 
        cum_time, cur = todo.pop()
76
 
        children = _total_stack[cur]
77
 
 
78
 
        c_times = []
79
 
 
80
 
        info = _info[cur]
81
 
        if hide_fast and info[-1] < 0.0001:
82
 
            continue
83
 
 
84
 
        # Compute the module time by removing the children times
85
 
        mod_time = info[-1]
86
 
        for child in children:
87
 
            c_info = _info[child]
88
 
            mod_time -= c_info[-1]
89
 
            c_times.append((c_info[-1], child))
90
 
 
91
 
        # indent, cum_time, mod_time, name,
92
 
        # scope_name, frame_name, frame_lineno
93
 
        out_file.write('%5.1f %5.1f %-40s @ %s:%d\n'
94
 
            % (info[-1]*1000., mod_time*1000.,
95
 
               ('+'*info[0] + cur[1]),
96
 
               info[1], info[2]))
97
 
 
98
 
        if sorted:
99
 
            c_times.sort()
100
 
        else:
101
 
            c_times.reverse()
102
 
        todo.extend(c_times)
103
 
 
104
 
 
105
 
_real_import = __import__
106
 
 
107
 
def timed_import(name, globals=None, locals=None, fromlist=None, level=None):
108
 
    """Wrap around standard importer to log import time"""
109
 
    # normally there are 4, but if this is called as __import__ eg by
110
 
    # /usr/lib/python2.6/email/__init__.py then there may be only one
111
 
    # parameter
112
 
    # level is only passed by python2.6
113
 
 
114
 
    if globals is None:
115
 
        # can't determine the scope name afaics; we could peek up the stack to
116
 
        # see where this is being called from, but it should be a rare case.
117
 
        scope_name = None
118
 
    else:
119
 
        scope_name = globals.get('__name__', None)
120
 
        if scope_name is None:
121
 
            scope_name = globals.get('__file__', None)
122
 
        if scope_name is None:
123
 
            scope_name = globals.keys()
124
 
        else:
125
 
            # Trim out paths before bzrlib
126
 
            loc = scope_name.find('bzrlib')
127
 
            if loc != -1:
128
 
                scope_name = scope_name[loc:]
129
 
            # For stdlib, trim out early paths
130
 
            loc = scope_name.find('python2.4')
131
 
            if loc != -1:
132
 
                scope_name = scope_name[loc:]
133
 
 
134
 
    # Figure out the frame that is doing the importing
135
 
    frame = sys._getframe(1)
136
 
    frame_name = frame.f_globals.get('__name__', '<unknown>')
137
 
    extra = ''
138
 
    if frame_name.endswith('demandload'):
139
 
        # If this was demandloaded, we have 3 frames to ignore
140
 
        extra = '(demandload) '
141
 
        frame = sys._getframe(4)
142
 
        frame_name = frame.f_globals.get('__name__', '<unknown>')
143
 
    elif frame_name.endswith('lazy_import'):
144
 
        # If this was lazily imported, we have 3 frames to ignore
145
 
        extra = '[l] '
146
 
        frame = sys._getframe(4)
147
 
        frame_name = frame.f_globals.get('__name__', '<unknown>')
148
 
    if fromlist:
149
 
        extra += ' [%s]' % (', '.join(map(str, fromlist)),)
150
 
    frame_lineno = frame.f_lineno
151
 
 
152
 
    this = stack_add(extra + name, frame_name, frame_lineno, scope_name)
153
 
 
154
 
    tstart = _timer()
155
 
    try:
156
 
        # Do the import
157
 
        mod = _real_import(name, globals, locals, fromlist)
158
 
    finally:
159
 
        tload = _timer()-tstart
160
 
        stack_finish(this, tload)
161
 
 
162
 
    return mod
163
 
 
164
 
 
165
 
_real_compile = re._compile
166
 
 
167
 
 
168
 
def timed_compile(*args, **kwargs):
169
 
    """Log how long it takes to compile a regex"""
170
 
 
171
 
    # And who is requesting this?
172
 
    frame = sys._getframe(2)
173
 
    frame_name = frame.f_globals.get('__name__', '<unknown>')
174
 
 
175
 
    extra = ''
176
 
    if frame_name.endswith('lazy_regex'):
177
 
        # If this was lazily compiled, we have 3 more frames to ignore
178
 
        extra = '[l] '
179
 
        frame = sys._getframe(5)
180
 
        frame_name = frame.f_globals.get('__name__', '<unknown>')
181
 
    frame_lineno = frame.f_lineno
182
 
    this = stack_add(extra+repr(args[0]), frame_name, frame_lineno)
183
 
 
184
 
    tstart = _timer()
185
 
    try:
186
 
        # Measure the compile time
187
 
        comp = _real_compile(*args, **kwargs)
188
 
    finally:
189
 
        tcompile = _timer() - tstart
190
 
        stack_finish(this, tcompile)
191
 
 
192
 
    return comp
193
 
 
194
 
 
195
 
def install():
196
 
    """Install the hooks for measuring import and regex compile time."""
197
 
    __builtins__['__import__'] = timed_import
198
 
    re._compile = timed_compile
199
 
 
200
 
 
201
 
def uninstall():
202
 
    """Remove the import and regex compile timing hooks."""
203
 
    __builtins__['__import__'] = _real_import
204
 
    re._compile = _real_compile
205