Skip to content

Commit 94e478a

Browse files
committed
implement and use resolve_many_addr
it uses _vmprof.resolve_many_addr on pypy, which is *much* more efficient
1 parent 38d9e27 commit 94e478a

File tree

4 files changed

+53
-8
lines changed

4 files changed

+53
-8
lines changed

vmprof/__init__.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,3 +137,19 @@ def get_profile_path():
137137
if hasattr(_vmprof, 'get_profile_path'):
138138
return _vmprof.get_profile_path()
139139
raise NotImplementedError("get_profile_path not implemented on this platform")
140+
141+
def resolve_many_addr(addrs):
142+
""" Try to symbolicate the function addresses in addrs to triples of
143+
(function_name, line_number or 0, sourcefile or shared library)
144+
returns a dictionary mapping the addresses where that worked to said triples.
145+
"""
146+
if hasattr(_vmprof, 'resolve_many_addr'):
147+
return _vmprof.resolve_many_addr(addrs)
148+
if hasattr(_vmprof, 'resolve_addr'):
149+
res = {}
150+
for addr in addrs:
151+
info = _vmprof.resolve_addr(addr)
152+
if info is not None:
153+
res[addr] = info
154+
return res
155+
return {} # valid result to always know nothing

vmprof/reader.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -310,24 +310,24 @@ def setup(self):
310310
self.dedup = set()
311311

312312
def finished_reading_profile(self):
313-
import _vmprof
313+
import _vmprof, vmprof
314314
if not hasattr(_vmprof, 'resolve_addr'):
315315
# windows does not implement that!
316316
return
317317

318-
resolve_addr = _vmprof.resolve_addr
319-
from _vmprof import resolve_addr
320318
LogReader.finished_reading_profile(self)
321319
if len(self.dedup) == 0:
322320
return
321+
all_addresses = vmprof.resolve_many_addr(self.dedup)
322+
323323
self.fileobj.seek(0, os.SEEK_END)
324324
# must match '<lang>:<name>:<line>:<file>'
325325
# 'n' has been chosen as lang here, because the symbol
326326
# can be generated from several languages (e.g. C, C++, ...)
327327

328328
for addr in self.dedup:
329-
bytelist = [b"\x08"]
330-
result = resolve_addr(addr)
329+
bytelist = [MARKER_NATIVE_SYMBOLS]
330+
result = all_addresses.get(addr)
331331
if result is None:
332332
name, lineno, srcfile = None, 0, None
333333
else:
@@ -348,6 +348,8 @@ def add_virtual_ip(self, marker, unique_id, name):
348348

349349
def add_trace(self, trace, trace_count, thread_id, mem_in_kb):
350350
for addr in trace:
351+
if not isinstance(addr, NativeCode):
352+
continue
351353
if addr not in self.dedup:
352354
self.dedup.add(addr)
353355

vmprof/test/test_c_symboltable.py

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
//void dump_all_known_symbols(int fd);
1212
int test_extract(char ** name, int * lineno, char ** src);
1313
int test_extract_sofile(char ** name, int * lineno, char ** src);
14+
15+
int somefunc();
16+
void* get_somefunc(int);
1417
""")
1518
with open("src/symboltable.c", "rb") as fd:
1619
source = fd.read().decode()
@@ -36,7 +39,16 @@
3639
return vmp_resolve_addr(&abs, gname, 64,
3740
lineno, gsrc, 128);
3841
}
42+
43+
int somefunc() {return 1;}
44+
void* get_somefunc(int which) {
45+
if (which == 0) return &somefunc;
46+
if (which == 1) return &abs;
47+
return NULL;
48+
}
3949
"""
50+
# replace the name, otherwise we'll get the one built into pypy
51+
source = source.replace('vmp_resolve_addr', 'vmp_resolve_addr_2')
4052
libs = [] #['unwind', 'unwind-x86_64']
4153
includes = ['src']
4254
if sys.platform.startswith('linux'):
@@ -80,7 +92,7 @@ def test_resolve_addr(self):
8092
_lineno = ffi.new("int*")
8193
lib.test_extract(name, _lineno, src)
8294

83-
assert ffi.string(name[0]) == b"vmp_resolve_addr"
95+
assert ffi.string(name[0]) == b"vmp_resolve_addr_2"
8496
srcfile = ffi.string(src[0])
8597
assert b"_test_symboltable" in srcfile
8698
if not srcfile.endswith(b"vmprof/test/_test_symboltable.c"):
@@ -90,7 +102,7 @@ def test_resolve_addr(self):
90102
with open("vmprof/test/_test_symboltable.c", "rb") as fd:
91103
lineno = 1
92104
for line in fd.readlines():
93-
if "int vmp_resolve_addr(void * addr," in line.decode():
105+
if "int vmp_resolve_addr_2(void * addr," in line.decode():
94106
if _lineno[0] == lineno:
95107
break
96108
lineno += 1
@@ -116,3 +128,18 @@ def test_sofile_in_srcfile(self):
116128
elif sys.platform == "darwin":
117129
# osx
118130
assert b"libsystem_c.dylib" in ffi.string(src[0])
131+
132+
def test_vmprof_resolve_addr(self):
133+
import _vmprof
134+
res = _vmprof.resolve_addr(int(self.ffi.cast('intptr_t', self.lib.get_somefunc(0))))
135+
assert res[0] == b'somefunc'
136+
137+
def test_vmprof_resolve_many_addr(self):
138+
import vmprof
139+
addrs = [int(self.ffi.cast('intptr_t', self.lib.get_somefunc(which))) for which in [0, 1, 2]]
140+
res = vmprof.resolve_many_addr(addrs)
141+
assert len(res) <= 2
142+
if addrs[0] in res:
143+
assert res[addrs[0]][0] == b'somefunc'
144+
if addrs[1] in res:
145+
assert res[addrs[1]][0] == b'abs'

vmprof/test/test_run.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ def read(self, count):
5858
PY3K = True
5959
else:
6060
PY3K = False
61-
if hasattr(os, 'uname') and os.uname().machine == 'ppc64le':
61+
if hasattr(os, 'uname') and os.uname()[4] == 'ppc64le':
6262
PPC64LE = True
6363
else:
6464
PPC64LE = False

0 commit comments

Comments
 (0)