[pypy-commit] pypy default: merge the vmprof-0.4.10 branch:
antocuni
pypy.commits at gmail.com
Wed Nov 8 11:47:49 EST 2017
Author: Antonio Cuni <anto.cuni at gmail.com>
Branch:
Changeset: r92973:4b7ad9d4be0d
Date: 2017-11-08 17:47 +0100
http://bitbucket.org/pypy/pypy/changeset/4b7ad9d4be0d/
Log: merge the vmprof-0.4.10 branch:
- copy the recent changes to the C part of vmprof from github
- make sure that the tests are actually testing something: so far,
most of the were just silently skipped on the nightly buildbot :(
- test_native is broken: it has been broken since the merge of
vmprof-0.4.8, but we didn't notice
- I expect some tests to fail on weird architectures. Once we know
which, we can explicitly skip them
diff --git a/requirements.txt b/requirements.txt
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,4 +1,5 @@
cffi>=1.4.0
+vmprof>=0.4.10 # required to parse log files in rvmprof tests
# hypothesis is used for test generation on untranslated tests
hypothesis
diff --git a/rpython/rlib/rvmprof/src/shared/vmprof_common.c b/rpython/rlib/rvmprof/src/shared/vmprof_common.c
--- a/rpython/rlib/rvmprof/src/shared/vmprof_common.c
+++ b/rpython/rlib/rvmprof/src/shared/vmprof_common.c
@@ -32,12 +32,21 @@
static size_t threads_size = 0;
static size_t thread_count = 0;
static size_t threads_size_step = 8;
-#endif
int vmprof_get_itimer_type(void) {
return itimer_type;
}
+int vmprof_get_signal_type(void) {
+ return signal_type;
+}
+#endif
+
+#ifdef VMPROF_WINDOWS
+#include "vmprof_win.h"
+#endif
+
+
int vmprof_is_enabled(void) {
return is_enabled;
}
@@ -62,10 +71,6 @@
profile_interval_usec = value;
}
-int vmprof_get_signal_type(void) {
- return signal_type;
-}
-
char *vmprof_init(int fd, double interval, int memory,
int proflines, const char *interp_name, int native, int real_time)
{
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
@@ -15,7 +15,9 @@
#include <pthread.h>
#endif
+#ifdef VMPROF_UNIX
#include "vmprof_getpc.h"
+#endif
#ifdef VMPROF_LINUX
#include <syscall.h>
diff --git a/rpython/rlib/rvmprof/src/shared/vmprof_memory.c b/rpython/rlib/rvmprof/src/shared/vmprof_memory.c
--- a/rpython/rlib/rvmprof/src/shared/vmprof_memory.c
+++ b/rpython/rlib/rvmprof/src/shared/vmprof_memory.c
@@ -8,7 +8,7 @@
#include <mach/task_info.h>
static mach_port_t mach_task;
-#else
+#elif defined(VMPROF_UNIX)
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
diff --git a/rpython/rlib/rvmprof/src/shared/vmprof_unix.c b/rpython/rlib/rvmprof/src/shared/vmprof_unix.c
--- a/rpython/rlib/rvmprof/src/shared/vmprof_unix.c
+++ b/rpython/rlib/rvmprof/src/shared/vmprof_unix.c
@@ -41,8 +41,6 @@
void vmprof_ignore_signals(int ignored)
{
if (ignored) {
- /* set the last bit, and wait until concurrently-running signal
- handlers finish */
__sync_add_and_fetch(&signal_handler_ignore, 1L);
while (signal_handler_entries != 0L) {
usleep(1);
@@ -370,7 +368,7 @@
goto error;
if (install_sigprof_timer() == -1)
goto error;
- vmprof_ignore_signals(0);
+ signal_handler_ignore = 0;
return 0;
error:
@@ -394,7 +392,7 @@
int vmprof_disable(void)
{
- vmprof_ignore_signals(1);
+ signal_handler_ignore = 1;
vmprof_set_profile_interval_usec(0);
#ifdef VMP_SUPPORTS_NATIVE_PROFILING
disable_cpyprof();
diff --git a/rpython/rlib/rvmprof/src/shared/vmprof_win.c b/rpython/rlib/rvmprof/src/shared/vmprof_win.c
--- a/rpython/rlib/rvmprof/src/shared/vmprof_win.c
+++ b/rpython/rlib/rvmprof/src/shared/vmprof_win.c
@@ -1,7 +1,7 @@
-// cannot include this header because it also has definitions
-#include "windows.h"
-#include "compat.h"
-#include "vmp_stack.h"
+#include "vmprof_win.h"
+
+volatile int thread_started = 0;
+volatile int enabled = 0;
HANDLE write_mutex;
@@ -12,7 +12,20 @@
return 0;
}
-#include <tlhelp32.h>
+int vmprof_register_virtual_function(char *code_name, intptr_t code_uid,
+ int auto_retry)
+{
+ char buf[2048];
+ long namelen;
+
+ namelen = (long)strnlen(code_name, 1023);
+ buf[0] = MARKER_VIRTUAL_IP;
+ *(intptr_t*)(buf + 1) = code_uid;
+ *(long*)(buf + 1 + sizeof(intptr_t)) = namelen;
+ memcpy(buf + 1 + sizeof(intptr_t) + sizeof(long), code_name, namelen);
+ vmp_write_all(buf, 1 + sizeof(intptr_t) + sizeof(long) + namelen);
+ return 0;
+}
int vmp_write_all(const char *buf, size_t bufsize)
{
@@ -40,3 +53,168 @@
return 0;
}
+HANDLE write_mutex;
+
+#include "vmprof_common.h"
+
+int vmprof_snapshot_thread(DWORD thread_id, PY_WIN_THREAD_STATE *tstate, prof_stacktrace_s *stack)
+{
+ HRESULT result;
+ HANDLE hThread;
+ int depth;
+ CONTEXT ctx;
+#ifdef RPYTHON_LL2CTYPES
+ return 0; // not much we can do
+#else
+#if !defined(RPY_TLOFS_thread_ident) && defined(RPYTHON_VMPROF)
+ return 0; // we can't freeze threads, unsafe
+#else
+ hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, thread_id);
+ if (!hThread) {
+ return -1;
+ }
+ result = SuspendThread(hThread);
+ if(result == 0xffffffff)
+ return -1; // possible, e.g. attached debugger or thread alread suspended
+ // find the correct thread
+#ifdef RPYTHON_VMPROF
+ ctx.ContextFlags = CONTEXT_FULL;
+ if (!GetThreadContext(hThread, &ctx))
+ return -1;
+ depth = get_stack_trace(tstate->vmprof_tl_stack,
+ stack->stack, MAX_STACK_DEPTH-2, ctx.Eip);
+ stack->depth = depth;
+ stack->stack[depth++] = thread_id;
+ stack->count = 1;
+ stack->marker = MARKER_STACKTRACE;
+ ResumeThread(hThread);
+ return depth;
+#else
+ depth = vmp_walk_and_record_stack(tstate->frame, stack->stack,
+ MAX_STACK_DEPTH, 0, 0);
+ stack->depth = depth;
+ stack->stack[depth++] = (void*)((ULONG_PTR)thread_id);
+ stack->count = 1;
+ stack->marker = MARKER_STACKTRACE;
+ ResumeThread(hThread);
+ return depth;
+#endif
+
+#endif
+#endif
+}
+
+#ifndef RPYTHON_VMPROF
+static
+PY_WIN_THREAD_STATE * get_current_thread_state(void)
+{
+#if PY_MAJOR_VERSION < 3
+ return _PyThreadState_Current;
+#elif PY_VERSION_HEX < 0x03050200
+ return (PyThreadState*) _Py_atomic_load_relaxed(&_PyThreadState_Current);
+#else
+ return _PyThreadState_UncheckedGet();
+#endif
+}
+#endif
+
+long __stdcall vmprof_mainloop(void *arg)
+{
+#ifdef RPYTHON_LL2CTYPES
+ // for tests only
+ return 0;
+#else
+ // it is not a test case!
+ PY_WIN_THREAD_STATE *tstate;
+ HANDLE hThreadSnap = INVALID_HANDLE_VALUE;
+ prof_stacktrace_s *stack = (prof_stacktrace_s*)malloc(SINGLE_BUF_SIZE);
+ int depth;
+#ifndef RPYTHON_VMPROF
+ // cpython version
+ while (1) {
+ Sleep(vmprof_get_profile_interval_usec() * 1000);
+ if (!enabled) {
+ continue;
+ }
+ tstate = get_current_thread_state();
+ if (!tstate)
+ continue;
+ depth = vmprof_snapshot_thread(tstate->thread_id, tstate, stack);
+ if (depth > 0) {
+ vmp_write_all((char*)stack + offsetof(prof_stacktrace_s, marker),
+ SIZEOF_PROF_STACKTRACE + depth * sizeof(void*));
+ }
+ }
+#else
+ // pypy version
+ while (1) {
+ //Sleep(vmprof_get_profile_interval_usec() * 1000);
+ Sleep(10);
+ if (!enabled) {
+ continue;
+ }
+ _RPython_ThreadLocals_Acquire();
+ tstate = _RPython_ThreadLocals_Head(); // the first one is one behind head
+ tstate = _RPython_ThreadLocals_Enum(tstate);
+ while (tstate) {
+ if (tstate->ready == 42) {
+ depth = vmprof_snapshot_thread(tstate->thread_ident, tstate, stack);
+ if (depth > 0) {
+ vmp_write_all((char*)stack + offsetof(prof_stacktrace_s, marker),
+ depth * sizeof(void *) +
+ sizeof(struct prof_stacktrace_s) -
+ offsetof(struct prof_stacktrace_s, marker));
+ }
+ }
+ tstate = _RPython_ThreadLocals_Enum(tstate);
+ }
+ _RPython_ThreadLocals_Release();
+ }
+#endif
+#endif
+}
+
+RPY_EXTERN
+int vmprof_enable(int memory, int native, int real_time)
+{
+ if (!thread_started) {
+ if (!CreateThread(NULL, 0, vmprof_mainloop, NULL, 0, NULL)) {
+ return -1;
+ }
+ thread_started = 1;
+ }
+ enabled = 1;
+ return 0;
+}
+
+RPY_EXTERN
+int vmprof_disable(void)
+{
+ char marker = MARKER_TRAILER;
+ (void)vmp_write_time_now(MARKER_TRAILER);
+
+ enabled = 0;
+ vmp_set_profile_fileno(-1);
+ return 0;
+}
+
+RPY_EXTERN
+void vmprof_ignore_signals(int ignored)
+{
+ enabled = !ignored;
+}
+
+int vmp_native_enable(void)
+{
+ return 0;
+}
+
+void vmp_native_disable(void)
+{
+}
+
+int get_stack_trace(PY_WIN_THREAD_STATE * current, void** result,
+ int max_depth, intptr_t pc)
+{
+ return 0;
+}
diff --git a/rpython/rlib/rvmprof/src/shared/vmprof_win.h b/rpython/rlib/rvmprof/src/shared/vmprof_win.h
--- a/rpython/rlib/rvmprof/src/shared/vmprof_win.h
+++ b/rpython/rlib/rvmprof/src/shared/vmprof_win.h
@@ -3,20 +3,13 @@
#include "windows.h"
#include "compat.h"
#include "vmp_stack.h"
-
-HANDLE write_mutex;
+#include <tlhelp32.h>
int prepare_concurrent_bufs(void);
-#include "vmprof_common.h"
-#include <tlhelp32.h>
-
// This file has been inspired (but not copied from since the LICENSE
// would not allow it) from verysleepy profiler
-volatile int thread_started = 0;
-volatile int enabled = 0;
-
int vmp_write_all(const char *buf, size_t bufsize);
#ifdef RPYTHON_VMPROF
@@ -26,178 +19,14 @@
#endif
-RPY_EXTERN
int vmprof_register_virtual_function(char *code_name, intptr_t code_uid,
- int auto_retry)
-{
- char buf[2048];
- long namelen;
+ int auto_retry);
- namelen = (long)strnlen(code_name, 1023);
- buf[0] = MARKER_VIRTUAL_IP;
- *(intptr_t*)(buf + 1) = code_uid;
- *(long*)(buf + 1 + sizeof(intptr_t)) = namelen;
- memcpy(buf + 1 + sizeof(intptr_t) + sizeof(long), code_name, namelen);
- vmp_write_all(buf, 1 + sizeof(intptr_t) + sizeof(long) + namelen);
- return 0;
-}
-
-int vmprof_snapshot_thread(DWORD thread_id, PY_WIN_THREAD_STATE *tstate, prof_stacktrace_s *stack)
-{
- HRESULT result;
- HANDLE hThread;
- int depth;
- CONTEXT ctx;
-#ifdef RPYTHON_LL2CTYPES
- return 0; // not much we can do
-#else
-#if !defined(RPY_TLOFS_thread_ident) && defined(RPYTHON_VMPROF)
- return 0; // we can't freeze threads, unsafe
-#else
- hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, thread_id);
- if (!hThread) {
- return -1;
- }
- result = SuspendThread(hThread);
- if(result == 0xffffffff)
- return -1; // possible, e.g. attached debugger or thread alread suspended
- // find the correct thread
-#ifdef RPYTHON_VMPROF
- ctx.ContextFlags = CONTEXT_FULL;
- if (!GetThreadContext(hThread, &ctx))
- return -1;
- depth = get_stack_trace(tstate->vmprof_tl_stack,
- stack->stack, MAX_STACK_DEPTH-2, ctx.Eip);
- stack->depth = depth;
- stack->stack[depth++] = thread_id;
- stack->count = 1;
- stack->marker = MARKER_STACKTRACE;
- ResumeThread(hThread);
- return depth;
-#else
- depth = vmp_walk_and_record_stack(tstate->frame, stack->stack,
- MAX_STACK_DEPTH, 0, 0);
- stack->depth = depth;
- stack->stack[depth++] = (void*)((ULONG_PTR)thread_id);
- stack->count = 1;
- stack->marker = MARKER_STACKTRACE;
- ResumeThread(hThread);
- return depth;
-#endif
-
-#endif
-#endif
-}
-
-#ifndef RPYTHON_VMPROF
-static
-PY_WIN_THREAD_STATE * get_current_thread_state(void)
-{
-#if PY_MAJOR_VERSION < 3
- return _PyThreadState_Current;
-#elif PY_VERSION_HEX < 0x03050200
- return (PyThreadState*) _Py_atomic_load_relaxed(&_PyThreadState_Current);
-#else
- return _PyThreadState_UncheckedGet();
-#endif
-}
-#endif
-
-long __stdcall vmprof_mainloop(void *arg)
-{
-#ifdef RPYTHON_LL2CTYPES
- // for tests only
- return 0;
-#else
- // it is not a test case!
- PY_WIN_THREAD_STATE *tstate;
- HANDLE hThreadSnap = INVALID_HANDLE_VALUE;
- prof_stacktrace_s *stack = (prof_stacktrace_s*)malloc(SINGLE_BUF_SIZE);
- int depth;
-#ifndef RPYTHON_VMPROF
- // cpython version
- while (1) {
- Sleep(profile_interval_usec * 1000);
- if (!enabled) {
- continue;
- }
- tstate = get_current_thread_state();
- if (!tstate)
- continue;
- depth = vmprof_snapshot_thread(tstate->thread_id, tstate, stack);
- if (depth > 0) {
- vmp_write_all((char*)stack + offsetof(prof_stacktrace_s, marker),
- SIZEOF_PROF_STACKTRACE + depth * sizeof(void*));
- }
- }
-#else
- // pypy version
- while (1) {
- //Sleep(profile_interval_usec * 1000);
- Sleep(10);
- if (!enabled) {
- continue;
- }
- _RPython_ThreadLocals_Acquire();
- tstate = _RPython_ThreadLocals_Head(); // the first one is one behind head
- tstate = _RPython_ThreadLocals_Enum(tstate);
- while (tstate) {
- if (tstate->ready == 42) {
- depth = vmprof_snapshot_thread(tstate->thread_ident, tstate, stack);
- if (depth > 0) {
- vmp_write_all((char*)stack + offsetof(prof_stacktrace_s, marker),
- depth * sizeof(void *) +
- sizeof(struct prof_stacktrace_s) -
- offsetof(struct prof_stacktrace_s, marker));
- }
- }
- tstate = _RPython_ThreadLocals_Enum(tstate);
- }
- _RPython_ThreadLocals_Release();
- }
-#endif
-#endif
-}
-
-RPY_EXTERN
-int vmprof_enable(int memory, int native, int real_time)
-{
- if (!thread_started) {
- if (!CreateThread(NULL, 0, vmprof_mainloop, NULL, 0, NULL)) {
- return -1;
- }
- thread_started = 1;
- }
- enabled = 1;
- return 0;
-}
-
-RPY_EXTERN
-int vmprof_disable(void)
-{
- char marker = MARKER_TRAILER;
- (void)vmp_write_time_now(MARKER_TRAILER);
-
- enabled = 0;
- vmp_set_profile_fileno(-1);
- return 0;
-}
-
-RPY_EXTERN
-void vmprof_ignore_signals(int ignored)
-{
- enabled = !ignored;
-}
-
-int vmp_native_enable(void) {
- return 0;
-}
-
-void vmp_native_disable(void) {
-}
-
+PY_WIN_THREAD_STATE * get_current_thread_state(void);
+int vmprof_enable(int memory, int native, int real_time);
+int vmprof_disable(void);
+void vmprof_ignore_signals(int ignored);
+int vmp_native_enable(void);
+void vmp_native_disable(void);
int get_stack_trace(PY_WIN_THREAD_STATE * current, void** result,
- int max_depth, intptr_t pc)
-{
- return 0;
-}
+ int max_depth, intptr_t pc);
diff --git a/rpython/rlib/rvmprof/test/test_file.py b/rpython/rlib/rvmprof/test/test_file.py
--- a/rpython/rlib/rvmprof/test/test_file.py
+++ b/rpython/rlib/rvmprof/test/test_file.py
@@ -2,25 +2,43 @@
import urllib2, py
from os.path import join
+RVMPROF = py.path.local(__file__).join('..', '..')
def github_raw_file(repo, path, branch='master'):
- return "https://raw.githubusercontent.com/{repo}/{branch}/{path}".format(**dict(
- repo=repo, path=path, branch=branch
- ))
+ url = "https://raw.githubusercontent.com/{repo}/{branch}/{path}"
+ return url.format(repo=repo, path=path, branch=branch)
+def get_list_of_files(shared):
+ files = list(shared.visit('*.[ch]'))
+ # in PyPy we checkin the result of ./configure; as such, these files are
+ # not in github and can be skipped
+ files.remove(shared.join('libbacktrace', 'config-x86_32.h'))
+ files.remove(shared.join('libbacktrace', 'config-x86_64.h'))
+ files.remove(shared.join('libbacktrace', 'gstdint.h'))
+ return files
def test_same_file():
- for root, dirs, files in os.walk('rpython/rlib/rvmprof/src/shared'):
- for file in files:
- if not (file.endswith(".c") or file.endswith(".h")):
- continue
- url = github_raw_file("vmprof/vmprof-python", "src/%s" % file)
- source = urllib2.urlopen(url).read()
- #
- dest = py.path.local(join(root, file)).read()
- if source != dest:
- raise AssertionError("%s was updated, but changes were"
- "not copied over to PyPy" % url)
- else:
- print("%s matches" % url)
- break # do not walk dirs
+ shared = RVMPROF.join('src', 'shared')
+ files = get_list_of_files(shared)
+ assert files, 'cannot find any C file, probably the directory is wrong?'
+ no_matches = []
+ print
+ for file in files:
+ path = file.relto(shared)
+ url = github_raw_file("vmprof/vmprof-python", "src/%s" % path)
+ source = urllib2.urlopen(url).read()
+ dest = file.read()
+ shortname = file.relto(RVMPROF)
+ if source == dest:
+ print '%s matches' % shortname
+ else:
+ print '%s does NOT match' % shortname
+ no_matches.append(file)
+ #
+ if no_matches:
+ print
+ print 'The following file dit NOT match'
+ for f in no_matches:
+ print ' ', f.relto(RVMPROF)
+ raise AssertionError("some files were updated on github, "
+ "but were not copied here")
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
@@ -1,214 +1,183 @@
import py, os
+import pytest
+import time
from rpython.tool.udir import udir
from rpython.rlib import rvmprof
from rpython.translator.c.test.test_genc import compile
-from rpython.rlib.objectmodel import we_are_translated
-from rpython.rlib.nonconst import NonConstant
from rpython.translator.tool.cbuild import ExternalCompilationInfo
from rpython.rtyper.lltypesystem import rffi, lltype
+ at pytest.mark.usefixtures('init')
+class RVMProfTest(object):
-def test_vmprof_execute_code_1():
+ ENTRY_POINT_ARGS = ()
- class MyCode:
- pass
- try:
- rvmprof.register_code_object_class(MyCode, lambda code: 'some code')
- except rvmprof.VMProfPlatformUnsupported:
- pass
+ class MyCode(object):
+ def __init__(self, name='py:code:0:noname'):
+ self.name = name
- @rvmprof.vmprof_execute_code("xcode1", lambda code, num: code)
- def main(code, num):
+ def get_name(self):
+ return self.name
+
+ @pytest.fixture
+ def init(self):
+ self.register()
+ self.rpy_entry_point = compile(self.entry_point, self.ENTRY_POINT_ARGS)
+
+ def register(self):
+ rvmprof.register_code_object_class(self.MyCode,
+ self.MyCode.get_name)
+
+
+class TestExecuteCode(RVMProfTest):
+
+ def entry_point(self):
+ res = self.main(self.MyCode(), 5)
+ assert res == 42
+ return 0
+
+ @rvmprof.vmprof_execute_code("xcode1", lambda self, code, num: code)
+ def main(self, code, num):
print num
return 42
- def f():
- res = main(MyCode(), 5)
+ def test(self):
+ assert self.entry_point() == 0
+ assert self.rpy_entry_point() == 0
+
+
+class TestResultClass(RVMProfTest):
+
+ class A: pass
+
+ @rvmprof.vmprof_execute_code("xcode2", lambda self, num, code: code,
+ result_class=A)
+ def main(self, num, code):
+ print num
+ return self.A()
+
+ def entry_point(self):
+ a = self.main(7, self.MyCode())
+ assert isinstance(a, self.A)
+ return 0
+
+ def test(self):
+ assert self.entry_point() == 0
+ assert self.rpy_entry_point() == 0
+
+
+class TestRegisterCode(RVMProfTest):
+
+ @rvmprof.vmprof_execute_code("xcode1", lambda self, code, num: code)
+ def main(self, code, num):
+ print num
+ return 42
+
+ def entry_point(self):
+ code = self.MyCode()
+ rvmprof.register_code(code, lambda code: 'some code')
+ res = self.main(code, 5)
assert res == 42
return 0
- assert f() == 0
- fn = compile(f, [])
- assert fn() == 0
+ def test(self):
+ assert self.entry_point() == 0
+ assert self.rpy_entry_point() == 0
-def test_vmprof_execute_code_2():
+class RVMProfSamplingTest(RVMProfTest):
- class MyCode:
- pass
- try:
- rvmprof.register_code_object_class(MyCode, lambda code: 'some code')
- except rvmprof.VMProfPlatformUnsupported:
- pass
+ # the kernel will deliver SIGPROF at max 250 Hz. See also
+ # https://github.com/vmprof/vmprof-python/issues/163
+ SAMPLING_INTERVAL = 1/250.0
- class A:
- pass
+ @pytest.fixture
+ def init(self, tmpdir):
+ self.tmpdir = tmpdir
+ self.tmpfile = tmpdir.join('profile.vmprof')
+ self.tmpfilename = str(self.tmpfile)
+ super(RVMProfSamplingTest, self).init()
- @rvmprof.vmprof_execute_code("xcode2", lambda num, code: code,
- result_class=A)
- def main(num, code):
- print num
- return A()
+ ENTRY_POINT_ARGS = (int, float)
+ def entry_point(self, value, delta_t):
+ code = self.MyCode('py:code:52:test_enable')
+ rvmprof.register_code(code, self.MyCode.get_name)
+ fd = os.open(self.tmpfilename, os.O_WRONLY | os.O_CREAT, 0666)
+ rvmprof.enable(fd, self.SAMPLING_INTERVAL)
+ start = time.time()
+ res = 0
+ while time.time() < start+delta_t:
+ res = self.main(code, value)
+ rvmprof.disable()
+ os.close(fd)
+ return res
- def f():
- a = main(7, MyCode())
- assert isinstance(a, A)
- return 0
+ def approx_equal(self, a, b, tolerance=0.1):
+ max_diff = (a+b)/2.0 * tolerance
+ return abs(a-b) < max_diff
- assert f() == 0
- fn = compile(f, [])
- assert fn() == 0
+class TestEnable(RVMProfSamplingTest):
-def test_register_code():
-
- class MyCode:
- pass
- try:
- rvmprof.register_code_object_class(MyCode, lambda code: 'some code')
- except rvmprof.VMProfPlatformUnsupported as e:
- py.test.skip(str(e))
-
- @rvmprof.vmprof_execute_code("xcode1", lambda code, num: code)
- def main(code, num):
- print num
- return 42
-
- def f():
- code = MyCode()
- rvmprof.register_code(code, lambda code: 'some code')
- res = main(code, 5)
- assert res == 42
- return 0
-
- assert f() == 0
- fn = compile(f, [], gcpolicy="minimark")
- assert fn() == 0
-
-
-def test_enable():
-
- class MyCode:
- pass
- def get_name(code):
- return 'py:code:52:x'
- try:
- rvmprof.register_code_object_class(MyCode, get_name)
- except rvmprof.VMProfPlatformUnsupported as e:
- py.test.skip(str(e))
-
- @rvmprof.vmprof_execute_code("xcode1", lambda code, num: code)
- def main(code, num):
- print num
+ @rvmprof.vmprof_execute_code("xcode1", lambda self, code, count: code)
+ def main(self, code, count):
s = 0
- for i in range(num):
+ for i in range(count):
s += (i << 1)
- if s % 2123423423 == 0:
- print s
return s
- tmpfilename = str(udir.join('test_rvmprof'))
+ def test(self):
+ from vmprof import read_profile
+ assert self.entry_point(10**4, 0.1) == 99990000
+ assert self.tmpfile.check()
+ self.tmpfile.remove()
+ #
+ assert self.rpy_entry_point(10**4, 0.5) == 99990000
+ assert self.tmpfile.check()
+ prof = read_profile(self.tmpfilename)
+ tree = prof.get_tree()
+ assert tree.name == 'py:code:52:test_enable'
+ assert self.approx_equal(tree.count, 0.5/self.SAMPLING_INTERVAL)
- def f():
- if NonConstant(False):
- # Hack to give os.open() the correct annotation
- 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
+
+class TestNative(RVMProfSamplingTest):
+
+ @pytest.fixture
+ def init(self, tmpdir):
+ eci = ExternalCompilationInfo(compile_extra=['-g','-O0'],
+ separate_module_sources=["""
+ RPY_EXTERN int native_func(int d) {
+ int j = 0;
+ if (d > 0) {
+ return native_func(d-1);
+ } else {
+ for (int i = 0; i < 42000; i++) {
+ j += 1;
+ }
+ }
+ return j;
+ }
+ """])
+ self.native_func = rffi.llexternal("native_func", [rffi.INT], rffi.INT,
+ compilation_info=eci)
+ super(TestNative, self).init(tmpdir)
+
+ @rvmprof.vmprof_execute_code("xcode1", lambda self, code, count: code)
+ def main(self, code, count):
+ if count > 0:
+ return self.main(code, count-1)
else:
- num = 10000
- period = 0.9
- rvmprof.enable(fd, period)
- res = main(code, num)
- #assert res == 499999500000
- rvmprof.disable()
- os.close(fd)
- return 0
+ return self.native_func(100)
- def check_profile(filename):
- from vmprof import read_profile
-
- prof = read_profile(filename)
- assert prof.get_tree().name.startswith("py:")
- assert prof.get_tree().count
-
- assert f() == 0
- assert os.path.exists(tmpfilename)
- fn = compile(f, [], gcpolicy="minimark")
- assert fn() == 0
- try:
- import vmprof
- except ImportError:
- py.test.skip("vmprof unimportable")
- else:
- check_profile(tmpfilename)
- finally:
- assert os.path.exists(tmpfilename)
- os.unlink(tmpfilename)
-
-def test_native():
- eci = ExternalCompilationInfo(compile_extra=['-g','-O0'],
- separate_module_sources=["""
- RPY_EXTERN int native_func(int d) {
- int j = 0;
- if (d > 0) {
- return native_func(d-1);
- } else {
- for (int i = 0; i < 42000; i++) {
- j += d;
- }
- }
- return j;
- }
- """])
-
- native_func = rffi.llexternal("native_func", [rffi.INT], rffi.INT,
- compilation_info=eci)
-
- class MyCode:
- pass
- def get_name(code):
- return 'py:code:52:x'
-
- try:
- rvmprof.register_code_object_class(MyCode, get_name)
- except rvmprof.VMProfPlatformUnsupported as e:
- py.test.skip(str(e))
-
- @rvmprof.vmprof_execute_code("xcode1", lambda code, num: code)
- def main(code, num):
- if num > 0:
- return main(code, num-1)
- else:
- return native_func(100)
-
- tmpfilename = str(udir.join('test_rvmprof'))
-
- def f():
- if NonConstant(False):
- # Hack to give os.open() the correct annotation
- os.open('foo', 1, 1)
- code = MyCode()
- rvmprof.register_code(code, get_name)
- fd = os.open(tmpfilename, os.O_RDWR | os.O_CREAT, 0666)
- num = 10000
- period = 0.0001
- rvmprof.enable(fd, period, native=1)
- for i in range(num):
- res = main(code, 3)
- rvmprof.disable()
- os.close(fd)
- return 0
-
- def check_profile(filename):
+ def test(self):
+ # XXX: this test is known to fail since rev a4f077ba651c, but buildbot
+ # never ran it. FIXME.
from vmprof import read_profile
from vmprof.show import PrettyPrinter
-
- prof = read_profile(filename)
+ assert self.rpy_entry_point(3, 0.5) == 42000
+ assert self.tmpfile.check()
+ #
+ prof = read_profile(self.tmpfilename)
tree = prof.get_tree()
p = PrettyPrinter()
p._print_tree(tree)
@@ -227,16 +196,3 @@
del not_found[i]
break
assert not_found == []
-
- fn = compile(f, [], gcpolicy="incminimark", lldebug=True)
- assert fn() == 0
- try:
- import vmprof
- except ImportError:
- py.test.skip("vmprof unimportable")
- else:
- check_profile(tmpfilename)
- finally:
- assert os.path.exists(tmpfilename)
- os.unlink(tmpfilename)
-
diff --git a/rpython/translator/translator.py b/rpython/translator/translator.py
--- a/rpython/translator/translator.py
+++ b/rpython/translator/translator.py
@@ -141,6 +141,9 @@
if isinstance(func, FunctionGraph):
return func
result = []
+ if hasattr(func, 'im_func'):
+ # make it possible to translate bound methods
+ func = func.im_func
for graph in translator.graphs:
if getattr(graph, 'func', None) is func:
result.append(graph)
More information about the pypy-commit
mailing list