Author: Richard Plangger <[email protected]>
Branch: vmprof-native
Changeset: r90010:d671b63850ea
Date: 2017-02-08 19:37 +0100
http://bitbucket.org/pypy/pypy/changeset/d671b63850ea/
Log: some more changes to the native test
diff --git a/rpython/rlib/rvmprof/cintf.py b/rpython/rlib/rvmprof/cintf.py
--- a/rpython/rlib/rvmprof/cintf.py
+++ b/rpython/rlib/rvmprof/cintf.py
@@ -46,7 +46,7 @@
eci_kwds = dict(
include_dirs = [SRC, SHARED, BACKTRACE, UDIS86],
- includes = ['rvmprof.h', 'vmprof_stack.h'],
+ includes = ['rvmprof.h','vmprof_stack.h'],
libraries = _libs,
separate_module_files = [
SRC.join('rvmprof.c'),
@@ -99,6 +99,7 @@
return CInterface(locals())
+
class CInterface(object):
def __init__(self, namespace):
for k, v in namespace.iteritems():
diff --git a/rpython/rlib/rvmprof/src/rvmprof.c
b/rpython/rlib/rvmprof/src/rvmprof.c
--- a/rpython/rlib/rvmprof/src/rvmprof.c
+++ b/rpython/rlib/rvmprof/src/rvmprof.c
@@ -16,16 +16,3 @@
#include "shared/vmprof_main_win32.h"
#endif
-void dump_native_symbols(int fileno)
-{
-// TODO PyObject * mod = NULL;
-// TODO
-// TODO mod = PyImport_ImportModuleNoBlock("vmprof");
-// TODO if (mod == NULL)
-// TODO goto error;
-// TODO
-// TODO PyObject_CallMethod(mod, "dump_native_symbols", "(l)", fileno);
-// TODO
-// TODOerror:
-// TODO Py_XDECREF(mod);
-}
diff --git a/rpython/rlib/rvmprof/src/rvmprof.h
b/rpython/rlib/rvmprof/src/rvmprof.h
--- a/rpython/rlib/rvmprof/src/rvmprof.h
+++ b/rpython/rlib/rvmprof/src/rvmprof.h
@@ -21,7 +21,6 @@
#define RPY_EXPORTED extern __attribute__((visibility("default")))
#endif
-
RPY_EXTERN char *vmprof_init(int fd, double interval, int memory,
int lines, const char *interp_name, int native);
RPY_EXTERN void vmprof_ignore_signals(int);
diff --git a/rpython/rlib/rvmprof/src/shared/symboltable.c
b/rpython/rlib/rvmprof/src/shared/symboltable.c
--- a/rpython/rlib/rvmprof/src/shared/symboltable.c
+++ b/rpython/rlib/rvmprof/src/shared/symboltable.c
@@ -170,11 +170,6 @@
}
}
-#else
-// other platforms than linux & mac os x
-void dump_all_known_symbols(int fd) {
- // oh, nothing to do!! a not supported platform
-}
#endif
#ifdef __unix__
@@ -247,3 +242,193 @@
#endif
return 0;
}
+
+#ifdef RPYTHON_VMPROF
+
+#define WORD_SIZE sizeof(long)
+#define ADDR_SIZE sizeof(void*)
+#define MAXLEN 1024
+
+void _dump_native_symbol(int fileno, void * addr, char * sym, int linenumber,
char * filename) {
+ char natsym[64];
+ off_t pos_before;
+ struct str {
+ void * addr;
+ // NOTE windows 64, not supported yet
+ long size;
+ char str[1024];
+ } s;
+ pos_before = lseek(fileno, 0, SEEK_CUR);
+ lseek(fileno, 0, SEEK_END);
+
+ s.addr = addr;
+ /* must mach '<lang>:<name>:<line>:<file>'
+ * 'n' has been chosen as lang here, because the symbol
+ * can be generated from several languages (e.g. C, C++, ...)
+ */
+ // MARKER_NATIVE_SYMBOLS is \x08
+ write(fileno, "\x08", 1);
+ if (sym == NULL || sym[0] == '\x00') {
+ snprintf(natsym, 64, "<native symbol %p>", addr);
+ sym = natsym;
+ }
+ if (filename != NULL) {
+ s.size = snprintf(s.str, 1024, "n:%s:%d:%s", sym, linenumber,
filename);
+ } else {
+ s.size = snprintf(s.str, 1024, "n:%s:%d:-", sym, linenumber);
+ }
+ write(fileno, &s, sizeof(void*)+sizeof(long)+s.size);
+
+ lseek(fileno, pos_before, SEEK_SET);
+}
+
+int _skip_string(int fileno)
+{
+ long chars;
+ int count = read(fileno, &chars, sizeof(long));
+ LOG("reading string of %d chars\n", chars);
+ if (count <= 0) {
+ return 1;
+ }
+ lseek(fileno, chars, SEEK_CUR);
+
+ return 0;
+}
+
+int _skip_header(int fileno, int * version, int * flags)
+{
+ unsigned char r[4];
+ (void)read(fileno, r, 4);
+ unsigned char count = r[3];
+ *version = (r[0] & 0xff) << 8 | (r[1] & 0xff);
+ *flags = r[2];
+ lseek(fileno, (int)count, SEEK_CUR);
+ return 0;
+}
+
+long _read_word(int fileno)
+{
+ long w;
+ read(fileno, &w, WORD_SIZE);
+ return w;
+}
+
+void * _read_addr(int fileno)
+{
+ void * a;
+ read(fileno, &a, ADDR_SIZE);
+ return a;
+}
+
+int _skip_word(int fileno)
+{
+ lseek(fileno, WORD_SIZE, SEEK_CUR);
+ return 0;
+}
+
+int _skip_addr(int fileno)
+{
+ lseek(fileno, ADDR_SIZE, SEEK_CUR);
+ return 0;
+}
+
+int _skip_time_and_zone(int fileno)
+{
+ lseek(fileno, sizeof(int64_t)*2 + 8, SEEK_CUR);
+ return 0;
+}
+
+
+void dump_native_symbols(int fileno)
+{
+ // only call this function
+ off_t orig_pos, cur_pos;
+ char marker;
+ ssize_t count;
+ int version;
+ int flags;
+ int memory, lines, native;
+ orig_pos = lseek(fileno, 0, SEEK_CUR);
+
+ lseek(fileno, 5*WORD_SIZE, SEEK_SET);
+
+ while (1) {
+ LOG("pre read\n");
+ count = read(fileno, &marker, 1);
+ LOG("post read\n");
+ if (count <= 0) {
+ break;
+ }
+ cur_pos = lseek(fileno, 0, SEEK_CUR);
+ LOG("posss 0x%llx %d\n", cur_pos-1, cur_pos-1);
+ switch (marker) {
+ case MARKER_HEADER: {
+ LOG("header 0x%llx\n", cur_pos);
+ if (_skip_header(fileno, &version, &flags) != 0) {
+ return;
+ }
+ memory = (flags & PROFILE_MEMORY) != 0;
+ native = (flags & PROFILE_NATIVE) != 0;
+ lines = (flags & PROFILE_LINES) != 0;
+ break;
+ } case MARKER_META: {
+ LOG("meta 0x%llx\n", cur_pos);
+ if (_skip_string(fileno) != 0) { return; }
+ if (_skip_string(fileno) != 0) { return; }
+ break;
+ } case MARKER_TIME_N_ZONE:
+ case MARKER_TRAILER: {
+ LOG("tnz or trailer 0x%llx\n", cur_pos);
+ if (_skip_time_and_zone(fileno) != 0) { return; }
+ break;
+ } case MARKER_VIRTUAL_IP:
+ case MARKER_NATIVE_SYMBOLS: {
+ LOG("virtip 0x%llx\n", cur_pos);
+ if (_skip_addr(fileno) != 0) { return; }
+ if (_skip_string(fileno) != 0) { return; }
+ break;
+ } case MARKER_STACKTRACE: {
+ long trace_count = _read_word(fileno);
+ long depth = _read_word(fileno);
+
+ LOG("stack 0x%llx %d %d\n", cur_pos, trace_count, depth);
+
+ for (long i = depth/2-1; i >= 0; i--) {
+ long kind = (long)_read_addr(fileno);
+ void * addr = _read_addr(fileno);
+ if (kind == VMPROF_NATIVE_TAG) {
+ LOG("found kind %p\n", addr);
+ char name[MAXLEN];
+ char srcfile[MAXLEN];
+ name[0] = 0;
+ srcfile[0] = 0;
+ int lineno = 0;
+ if (vmp_resolve_addr(addr, name, MAXLEN, &lineno,
srcfile, MAXLEN) == 0) {
+ LOG("dumping add %p, name %s, %s:%d\n", addr,
name, srcfile, lineno);
+ _dump_native_symbol(fileno, addr, name, lineno,
srcfile);
+ }
+ }
+ }
+ LOG("passed memory %d \n", memory);
+
+ if (_skip_addr(fileno) != 0) { return; } // thread id
+ if (memory) {
+ if (_skip_addr(fileno) != 0) { return; } // profile memory
+ }
+
+ break;
+ } default: {
+ fprintf(stderr, "unknown marker 0x%x\n", marker);
+ return;
+ }
+ }
+
+ cur_pos = lseek(fileno, 0, SEEK_CUR);
+ if (cur_pos >= orig_pos) {
+ break;
+ }
+ }
+
+ lseek(fileno, 0, SEEK_END);
+}
+#endif
diff --git a/rpython/rlib/rvmprof/src/shared/trampoline.c
b/rpython/rlib/rvmprof/src/shared/trampoline.c
--- a/rpython/rlib/rvmprof/src/shared/trampoline.c
+++ b/rpython/rlib/rvmprof/src/shared/trampoline.c
@@ -183,7 +183,7 @@
int pagesize;
if (g_trampoline != NULL) {
- fprintf(stderr, "trampoline already patched\n");
+ //fprintf(stderr, "trampoline already patched\n");
return 0; // already patched
}
diff --git a/rpython/rlib/rvmprof/src/shared/vmp_stack.c
b/rpython/rlib/rvmprof/src/shared/vmp_stack.c
--- a/rpython/rlib/rvmprof/src/shared/vmp_stack.c
+++ b/rpython/rlib/rvmprof/src/shared/vmp_stack.c
@@ -98,8 +98,6 @@
result[*depth] = (void*)CODE_ADDR_TO_UID(FRAME_CODE(frame));
*depth = *depth + 1;
#else
- //result[*depth] = (void*)CODE_ADDR_TO_UID(FRAME_CODE(frame));
- //*depth = *depth + 1;
if (frame->kind == VMPROF_CODE_TAG) {
int n = *depth;
@@ -107,12 +105,7 @@
result[n++] = (void*)frame->value;
*depth = n;
}
-#ifdef PYPY_JIT_CODEMAP
- else if (frame->kind == VMPROF_JITTED_TAG) {
- intptr_t pc = ((intptr_t*)(frame->value - sizeof(intptr_t)))[0];
- n = vmprof_write_header_for_jit_addr(result, n, pc, max_depth);
- }
-#endif
+
#endif
@@ -130,11 +123,15 @@
#ifdef VMP_SUPPORTS_NATIVE_PROFILING
int _write_native_stack(void* addr, void ** result, int depth) {
+#ifdef RPYTHON_VMPROF
+ result[depth++] = (void*)VMPROF_NATIVE_TAG;
+#else
if (vmp_profiles_python_lines()) {
// even if we do not log a python stack frame,
// we must keep the profile readable
result[depth++] = 0;
}
+#endif
result[depth++] = addr;
return depth;
}
@@ -143,16 +140,6 @@
int vmp_walk_and_record_stack(PY_STACK_FRAME_T *frame, void ** result,
int max_depth, int native_skip, intptr_t pc) {
-//#ifdef PYPY_JIT_CODEMAP
-// intptr_t codemap_addr;
-// if (pypy_find_codemap_at_addr((intptr_t)pc, &codemap_addr)) {
-// // the bottom part is jitted, means we can fill up the first part
-// // from the JIT
-// depth = vmprof_write_header_for_jit_addr(result, depth, pc,
max_depth);
-// frame = FRAME_STEP(frame); // skip the first item as it contains
garbage
-// }
-//#endif
-
// called in signal handler
#ifdef VMP_SUPPORTS_NATIVE_PROFILING
intptr_t func_addr;
@@ -179,12 +166,22 @@
native_skip--;
}
+ //printf("stack trace:\n");
int depth = 0;
PY_STACK_FRAME_T * top_most_frame = frame;
while (depth < max_depth) {
unw_get_proc_info(&cursor, &pip);
func_addr = pip.start_ip;
+
+ //{
+ // char name[64];
+ // unw_word_t x;
+ // unw_get_proc_name(&cursor, name, 64, &x);
+ // printf(" %s %p\n", name, func_addr);
+ //}
+
+
//if (func_addr == 0) {
// unw_word_t rip = 0;
// if (unw_get_reg(&cursor, UNW_REG_IP, &rip) < 0) {
@@ -197,6 +194,7 @@
if ((void*)pip.start_ip == (void*)VMPROF_EVAL()) {
// yes we found one stack entry of the python frames!
+#ifndef RPYTHON_VMPROF
unw_word_t rbx = 0;
if (unw_get_reg(&cursor, REG_RBX, &rbx) < 0) {
break;
@@ -208,6 +206,9 @@
// current top_most_frame
return 0;
} else {
+#else
+ {
+#endif
if (top_most_frame == NULL) {
break;
}
@@ -222,13 +223,27 @@
// mark native routines with the first bit set,
// this is possible because compiler align to 8 bytes.
//
- depth = _write_native_stack((void*)(func_addr | 0x1), result,
depth);
+
+#ifdef PYPY_JIT_CODEMAP
+ if (func_addr == 0 && top_most_frame->kind == VMPROF_JITTED_TAG) {
+ intptr_t pc = ((intptr_t*)(frame->value -
sizeof(intptr_t)))[0];
+ n = vmprof_write_header_for_jit_addr(result, n, pc, max_depth);
+ frame = FRAME_STEP(frame);
+ } else if (func_addr != 0) {
+ depth = _write_native_stack((void*)(func_addr | 0x1), result,
depth);
+ }
+#else
+ if (func_addr != 0) {
+ depth = _write_native_stack((void*)(func_addr | 0x1), result,
depth);
+ }
+#endif
}
int err = unw_step(&cursor);
- if (err <= 0) {
- // on mac this breaks on Py_Main?
+ if (err == 0) {
break;
+ } else if (err < 0) {
+ return 0; // this sample is broken, cannot walk it fully
}
}
@@ -256,15 +271,25 @@
int _ignore_symbols_from_path(const char * name) {
// which symbols should not be considered while walking
// the native stack?
+#ifdef RPYTHON_VMPROF
+ if (strstr(name, "libpypy-c.so") != NULL
+ || strstr(name, "pypy-c") != NULL
+ || strstr(name, "pypy") != NULL) {
+ printf("ignoring %s\n", name);
+ return 1;
+ }
+#else
+ // cpython
if (strstr(name, "python") != NULL &&
-#ifdef __unix__
+# ifdef __unix__
strstr(name, ".so\n") == NULL
-#elif defined(__APPLE__)
+# elif defined(__APPLE__)
strstr(name, ".so") == NULL
-#endif
+# endif
) {
return 1;
}
+#endif
return 0;
}
@@ -440,6 +465,9 @@
}
int vmp_ignore_ip(intptr_t ip) {
+ if (vmp_range_count == 0) {
+ return 0;
+ }
int i = vmp_binary_search_ranges(ip, vmp_ranges, vmp_range_count);
if (i == -1) {
return 0;
diff --git a/rpython/rlib/rvmprof/src/shared/vmprof.h
b/rpython/rlib/rvmprof/src/shared/vmprof.h
--- a/rpython/rlib/rvmprof/src/shared/vmprof.h
+++ b/rpython/rlib/rvmprof/src/shared/vmprof.h
@@ -1,5 +1,7 @@
#pragma once
+#include <unistd.h>
+
// common defines
#define MARKER_STACKTRACE '\x01'
#define MARKER_VIRTUAL_IP '\x02'
@@ -21,6 +23,7 @@
#define PROFILE_MEMORY '\x01'
#define PROFILE_LINES '\x02'
#define PROFILE_NATIVE '\x04'
+#define PROFILE_RPYTHON '\x08'
#ifdef VMPROF_UNIX
#define VMP_SUPPORTS_NATIVE_PROFILING
@@ -41,6 +44,9 @@
#define PY_THREAD_STATE_T void
#define FRAME_STEP(f) f->next
#define FRAME_CODE(f) f->
+// Is there is a way to tell the compiler
+// that this prototype can have ANY return value. Just removing
+// the return type will default to int
typedef long Signed;
RPY_EXTERN Signed __vmprof_eval_vmprof();
#define VMPROF_EVAL() __vmprof_eval_vmprof
diff --git a/rpython/rlib/rvmprof/src/shared/vmprof_common.h
b/rpython/rlib/rvmprof/src/shared/vmprof_common.h
--- a/rpython/rlib/rvmprof/src/shared/vmprof_common.h
+++ b/rpython/rlib/rvmprof/src/shared/vmprof_common.h
@@ -106,6 +106,9 @@
header.interp_name[2] = VERSION_TIMESTAMP;
header.interp_name[3] = memory*PROFILE_MEMORY + lines*PROFILE_LINES + \
native*PROFILE_NATIVE;
+#ifdef RPYTHON_VMPROF
+ header.interp_name[3] += PROFILE_RPYTHON;
+#endif
header.interp_name[4] = (char)namelen;
memcpy(&header.interp_name[5], interp_name, namelen);
diff --git a/rpython/rlib/rvmprof/src/vmprof_stack.h
b/rpython/rlib/rvmprof/src/vmprof_stack.h
--- a/rpython/rlib/rvmprof/src/vmprof_stack.h
+++ b/rpython/rlib/rvmprof/src/vmprof_stack.h
@@ -12,6 +12,7 @@
#define VMPROF_JITTING_TAG 4
#define VMPROF_GC_TAG 5
#define VMPROF_ASSEMBLER_TAG 6
+#define VMPROF_NATIVE_TAG 7
// whatever we want here
typedef struct vmprof_stack_s {
diff --git a/rpython/rlib/rvmprof/test/test_rvmprof.py
b/rpython/rlib/rvmprof/test/test_rvmprof.py
--- a/rpython/rlib/rvmprof/test/test_rvmprof.py
+++ b/rpython/rlib/rvmprof/test/test_rvmprof.py
@@ -154,7 +154,11 @@
eci = ExternalCompilationInfo(compile_extra=['-g','-O2'],
separate_module_sources=["""
RPY_EXTERN int native_func(void) {
- return 42;
+ int j = 0;
+ for (int i = 0; i < 420000; i++) {
+ j += 1;
+ }
+ return j;
}
"""])
@@ -176,8 +180,6 @@
if num > 0:
return main(code, num-1)
else:
- for i in range(100):
- native_func()
return native_func()
tmpfilename = str(udir.join('test_rvmprof'))
@@ -188,15 +190,12 @@
os.open('foo', 1, 1)
code = MyCode()
rvmprof.register_code(code, get_name)
- fd = os.open(tmpfilename, os.O_WRONLY | os.O_CREAT, 0666)
- if we_are_translated():
- num = 100000000
- period = 0.0001
- else:
- num = 10000
- period = 0.9
+ fd = os.open(tmpfilename, os.O_RDWR | os.O_CREAT, 0666)
+ num = 10000
+ period = 0.0001
rvmprof.enable(fd, period, native=1)
- res = main(code, num)
+ for i in range(num):
+ res = main(code, 10)
#assert res == 499999500000
rvmprof.disable()
os.close(fd)
@@ -204,10 +203,13 @@
def check_profile(filename):
from vmprof import read_profile
+ from vmprof.show import PrettyPrinter
prof = read_profile(filename)
- assert prof.get_tree().name.startswith("py:")
- assert prof.get_tree().count
+ tree = prof.get_tree()
+ p = PrettyPrinter()
+ p._print_tree(tree)
+ assert tree.name.startswith("n:pypy_g_main")
#assert f() == 0
#assert os.path.exists(tmpfilename)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit