Skip to content

Commit 390038c

Browse files
author
Jeff Weiss
committed
Performance improvements
Function that adds all function in a module to the depth control list
1 parent df27326 commit 390038c

File tree

2 files changed

+61
-8
lines changed

2 files changed

+61
-8
lines changed

function_trace/__init__.py

Lines changed: 60 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,13 @@ def _get_function_mapping(o):
9898
# the module and the function's name is '__call__'. The first arg is what's important
9999
# (the instance)
100100
if hasattr(o, '__call__'):
101-
#print "got mm %s" % o
102-
return (o.__call__, o.__call__)
101+
# print "got mm %s" % o
102+
try:
103+
# return (o.__call__.im_func.func_code, o.__call__)
104+
return (o.__call__, o.__call__)
105+
except:
106+
# print o
107+
return (None, None)
103108
return None
104109

105110

@@ -111,11 +116,17 @@ def _get_functions(self, functions, depths):
111116
'''
112117
self.functions = {}
113118
self.depths = {}
119+
functions = set(functions) | set(depths.keys())
114120
for f in functions:
115121
ident, info_obj = _get_function_mapping(f)
116122
self.functions[ident] = info_obj
117123
if f in depths:
118124
self.depths[ident] = depths[f]
125+
# self.count = 0
126+
# self.skipped = 0
127+
self.min_depth = sys.maxint
128+
# self.counts = {}
129+
self.no_trace = set()
119130

120131
def __init__(self, functions, formatter=None, depths=None):
121132
self.formatter = formatter or Formatter()
@@ -128,7 +139,9 @@ def _get_id(self, frame):
128139
'''
129140
Given a frame, figure out what function/method is being called.
130141
'''
142+
131143
f = frame.f_code
144+
# self.counts[f] = self.counts.get(f, 0) + 1
132145
if f in self.functions:
133146
return f # if it's in the functions dict, we know it's correct
134147
else:
@@ -166,8 +179,12 @@ def _method_or_function_call(self, frame, ident):
166179
self.trace_in(_name(f), [], args.locals)
167180

168181
def tracefunc(self, frame, event, arg):
182+
# self.counts[event] = self.counts.get(event, 0) + 1
169183
try:
170-
if event == 'call':
184+
if event == 'call' and frame.f_code not in self.no_trace:
185+
# return
186+
# f = frame.f_code
187+
# ident = f if f in self.functions else None
171188
ident = self._get_id(frame)
172189
if ident:
173190
additional_depth = self.depths.get(ident, None)
@@ -183,6 +200,13 @@ def tracefunc(self, frame, event, arg):
183200
if self.level <= min_depth_limit:
184201
self.tracedframes.append((frame.f_back, min_depth_limit,
185202
self.level < min_depth_limit))
203+
if min_depth_limit < self.min_depth:
204+
self.min_depth = min_depth_limit
205+
else:
206+
self.no_trace.add(frame.f_code)
207+
if self.level >= self.min_depth:
208+
# print "cut off! %s:%s" % (frame.f_code.co_filename, frame.f_lineno)
209+
return None
186210

187211
elif event == 'return':
188212
# print frame.f_code
@@ -193,7 +217,10 @@ def tracefunc(self, frame, event, arg):
193217
if self.tracedframes[-1][2]:
194218
# self.trace_out("%s: %s" % (self._get_id(frame), arg))
195219
self.trace_out(arg)
196-
self.tracedframes.pop()
220+
_x, min_depth_limit, _y = self.tracedframes.pop()
221+
if self.min_depth == min_depth_limit:
222+
# recalculate min depth
223+
self.min_depth = self._min_depths()
197224

198225
elif event == 'exception':
199226
if self.tracedframes and self.tracedframes[-1][0] is frame.f_back:
@@ -205,14 +232,22 @@ def tracefunc(self, frame, event, arg):
205232
if self.tracedframes[-1][2]:
206233
# self.trace_out("%s: %s" % (self._get_id(frame), arg))
207234
self.trace_out(arg[0], exception=True)
208-
self.tracedframes.pop()
235+
_x, min_depth_limit, _y = self.tracedframes.pop()
236+
if self.min_depth == min_depth_limit:
237+
# recalculate min depth
238+
self.min_depth = self._min_depths()
239+
209240
except:
210-
pass # just swallow errors to avoid interference with traced processes
211-
# raise # for debugging
241+
# pass # just swallow errors to avoid interference with traced processes
242+
raise # for debugging
212243
return self.tracefunc
213244

214245
def close(self):
215246
pass
247+
# print "count=%s, skipped=%s" % (self.count, self.skipped)
248+
# counts = sorted(self.counts.iteritems(), key=operator.itemgetter(1))
249+
# counts = counts[-50:]
250+
# print "count=%s, skipped=%s, counts=%s" % (self.count, self.skipped, counts)
216251

217252

218253
class StdoutTracer(Tracer):
@@ -228,6 +263,11 @@ def trace_out(self, r, exception=False):
228263
print self.formatter.format_output(self.level - 1, r, exception)
229264
sys.stdout.flush()
230265

266+
def close(self):
267+
# print "closing " + str(self.outputfile)
268+
# print "count=%s, skipped=%s, counts=%s" % (self.count, self.skipped, self.counts)
269+
pass
270+
231271

232272
class PerThreadFileTracer(Tracer):
233273
'''Print trace to a file. To get thread safety, use a different
@@ -251,6 +291,7 @@ def trace_out(self, r, exception=False):
251291

252292
def close(self):
253293
# print "closing " + str(self.outputfile)
294+
# print "count=%s, skipped=%s, counts=%s" % (self.count, self.skipped, self.counts)
254295
self.outputfile.close()
255296

256297

@@ -287,6 +328,18 @@ def r(x, y):
287328
return reduce(r, inspect.getmembers(o, callable), [])
288329

289330

331+
def add_all_at_depth(dct, module, lvl):
332+
'''takes a depth dict, module, and level, and adds all the functions
333+
in the module to the depth dict at the given level.
334+
335+
Returns: the dict with new values
336+
'''
337+
fns = all(module)
338+
for f in fns:
339+
dct[f] = lvl
340+
return dct
341+
342+
290343
@contextmanager
291344
def trace_on(objs=None, tracer=None):
292345
tracer = tracer or StdoutTracer(objs)

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from setuptools import setup, find_packages
22
setup(
33
name="function_trace",
4-
version="1.1.3",
4+
version="1.1.4",
55
packages=find_packages(),
66

77
# metadata for upload to PyPI

0 commit comments

Comments
 (0)