Skip to content

Commit 63b3fda

Browse files
HasenpfoteHasenpfote
authored andcommitted
Support for related traces
1 parent e953e3f commit 63b3fda

File tree

2 files changed

+130
-11
lines changed

2 files changed

+130
-11
lines changed

malloc_tracer/tracer.py

Lines changed: 83 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import math
66
import contextlib
77
import textwrap
8+
import os
9+
import linecache
810
from tracemalloc import start, take_snapshot, stop, Filter
911

1012

@@ -142,6 +144,40 @@ def extract_dependencies(obj):
142144
return collector.dependencies
143145

144146

147+
class TraceRecord(object):
148+
149+
def __init__(self, filepath, lineno, size):
150+
self._filepath = filepath
151+
self._lineno = lineno
152+
self._size = size
153+
154+
@property
155+
def filepath(self):
156+
return self._filepath
157+
158+
@property
159+
def short_filepath(self):
160+
return os.sep.join(self._filepath.split(os.sep)[-2:])
161+
162+
@property
163+
def lineno(self):
164+
return self._lineno
165+
166+
@property
167+
def size(self):
168+
return self._size
169+
170+
@property
171+
def human_readable_size(self):
172+
return bytes_to_hrf(self._size)
173+
174+
@property
175+
def line(self):
176+
line = linecache.getline(self._filepath, self._lineno).rstrip()
177+
#linecache.clearcache()
178+
return line
179+
180+
145181
class Tracer(object):
146182
'''Tracing malloc that occurs inside a function or method.
147183
@@ -235,7 +271,8 @@ def _take_snapshot(
235271
def trace(
236272
self,
237273
target_args=None,
238-
setup='pass'
274+
setup='pass',
275+
enable_related_traces=False
239276
):
240277
'''Display the trace result.
241278
@@ -248,28 +285,63 @@ def trace(
248285
target_args=target_args,
249286
setup=setup
250287
)
251-
snapshot = snapshot.filter_traces([Filter(True, DUMMY_SRC_NAME), ])
252-
stats = snapshot.statistics('lineno')
253288

254-
total = 0
255-
detected_lines = dict()
289+
traces_records = dict()
290+
stats = snapshot.statistics('lineno')
256291
for stat in stats:
257292
frame = stat.traceback[0]
258-
detected_lines[str(frame.lineno)] = stat.size
259-
total += stat.size
293+
key = frame.filename
294+
traces_record = traces_records.get(key)
295+
if traces_record is None:
296+
traces_records[key] = dict()
297+
traces_record = traces_records.get(key)
298+
299+
traces_record[frame.lineno] = TraceRecord(
300+
filepath=frame.filename,
301+
lineno=frame.lineno,
302+
size=stat.size
303+
)
260304

305+
# for DUMMY_SRC_NAME.
306+
print('<< Target traces >>')
261307
print('File "{}"'.format(self._filepath))
262-
print('Total {}(raw {} B)'.format(bytes_to_hrf(total), total))
263308
print('Line # Trace Line Contents')
264309
print('=' * (24+80))
265310

311+
traces_record = traces_records.get(DUMMY_SRC_NAME)
266312
source_text = ''.join(self._source_lines).rstrip()
267-
268313
for lineno, line in enumerate(source_text.split(sep='\n'), 1):
269-
size = detected_lines.get(str(lineno))
270-
trace = ' ' * 10 if size is None else bytes_to_hrf(size)
314+
if traces_record is None:
315+
trace = ' ' * 10
316+
else:
317+
tr = traces_record.get(lineno)
318+
trace = ' ' * 10 if tr is None else tr.human_readable_size
319+
271320
print('{lineno:6d} {trace:10s} {contents}'.format(
272321
lineno=self._lineno + lineno - 1,
273322
trace=trace,
274323
contents=line
275324
))
325+
326+
# for others.
327+
if enable_related_traces:
328+
related_traces_records = {k: v for k, v in traces_records.items() if k != DUMMY_SRC_NAME}
329+
if len(related_traces_records) > 0:
330+
print()
331+
print('<< Related traces >>')
332+
print('Line # Trace Line Contents')
333+
print('=' * (24+80))
334+
335+
for filepath, traces_record in sorted(related_traces_records.items()):
336+
print('File "{}"'.format(filepath))
337+
for lineno, tr in sorted(traces_record.items()):
338+
print('{lineno:6d} {trace:10s} {contents}'.format(
339+
lineno=tr.lineno,
340+
trace=tr.human_readable_size,
341+
contents=tr.line
342+
))
343+
344+
# Total allocated size.
345+
total = sum(stat.size for stat in stats)
346+
print()
347+
print('Total allocated size: {} (raw {} B)'.format(bytes_to_hrf(total), total))

test/test_tracer.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,11 @@ def test_function(self):
6969
target_args=dict(base=2, num=100),
7070
setup='import math as mathematics'
7171
)
72+
tracer.trace(
73+
target_args=dict(base=2, num=100),
74+
setup='import math as mathematics',
75+
enable_related_traces=True
76+
)
7277

7378
def test_function_with_default_args(self):
7479
tracer = Tracer(
@@ -80,6 +85,10 @@ def test_function_with_default_args(self):
8085
tracer.trace(
8186
setup='import math as mathematics'
8287
)
88+
tracer.trace(
89+
setup='import math as mathematics',
90+
enable_related_traces=True
91+
)
8392

8493
def test_function_with_auto_resolve_dependencies(self):
8594
tracer = Tracer(
@@ -88,6 +97,7 @@ def test_function_with_auto_resolve_dependencies(self):
8897
)
8998
with contextlib.redirect_stdout(None):
9099
tracer.trace()
100+
tracer.trace(enable_related_traces=True)
91101

92102
def test_method(self):
93103
instance = Klass(2, 100)
@@ -99,6 +109,10 @@ def test_method(self):
99109
tracer.trace(
100110
setup='import math as mathematics'
101111
)
112+
tracer.trace(
113+
setup='import math as mathematics',
114+
enable_related_traces=True
115+
)
102116

103117
def test_method_with_default_args(self):
104118
instance = Klass2()
@@ -111,6 +125,10 @@ def test_method_with_default_args(self):
111125
tracer.trace(
112126
setup='import math as mathematics'
113127
)
128+
tracer.trace(
129+
setup='import math as mathematics',
130+
enable_related_traces=True
131+
)
114132

115133
def test_method_with_auto_resolve_dependencies(self):
116134
instance = Klass2()
@@ -120,6 +138,7 @@ def test_method_with_auto_resolve_dependencies(self):
120138
)
121139
with contextlib.redirect_stdout(None):
122140
tracer.trace()
141+
tracer.trace(enable_related_traces=True)
123142

124143
def test_static_method(self):
125144
tracer = Tracer(
@@ -131,6 +150,11 @@ def test_static_method(self):
131150
target_args=dict(base=2, num=100),
132151
setup='import math as mathematics'
133152
)
153+
tracer.trace(
154+
target_args=dict(base=2, num=100),
155+
setup='import math as mathematics',
156+
enable_related_traces=True
157+
)
134158

135159
def test_static_method_with_default_args(self):
136160
tracer = Tracer(
@@ -143,6 +167,11 @@ def test_static_method_with_default_args(self):
143167
target_args=dict(base=2, num=100),
144168
setup='import math as mathematics'
145169
)
170+
tracer.trace(
171+
target_args=dict(base=2, num=100),
172+
setup='import math as mathematics',
173+
enable_related_traces=True
174+
)
146175

147176
def test_static_method_with_auto_resolve_dependencies(self):
148177
tracer = Tracer(
@@ -153,6 +182,10 @@ def test_static_method_with_auto_resolve_dependencies(self):
153182
tracer.trace(
154183
target_args=dict(base=2, num=100),
155184
)
185+
tracer.trace(
186+
target_args=dict(base=2, num=100),
187+
enable_related_traces=True
188+
)
156189

157190
def test_class_method(self):
158191
tracer = Tracer(
@@ -164,6 +197,11 @@ def test_class_method(self):
164197
target_args=dict(base=1),
165198
setup='import math as mathematics',
166199
)
200+
tracer.trace(
201+
target_args=dict(base=1),
202+
setup='import math as mathematics',
203+
enable_related_traces=True
204+
)
167205

168206
def test_class_method_with_default_args(self):
169207
tracer = Tracer(
@@ -176,6 +214,11 @@ def test_class_method_with_default_args(self):
176214
target_args=dict(base=1),
177215
setup='import math as mathematics',
178216
)
217+
tracer.trace(
218+
target_args=dict(base=1),
219+
setup='import math as mathematics',
220+
enable_related_traces=True
221+
)
179222

180223
def test_class_method_with_auto_resolve_dependencies(self):
181224
tracer = Tracer(
@@ -186,3 +229,7 @@ def test_class_method_with_auto_resolve_dependencies(self):
186229
tracer.trace(
187230
target_args=dict(base=1),
188231
)
232+
tracer.trace(
233+
target_args=dict(base=1),
234+
enable_related_traces=True
235+
)

0 commit comments

Comments
 (0)