diff --git a/src/_vmprof.c b/src/_vmprof.c index f96feb20..e51dc9e3 100644 --- a/src/_vmprof.c +++ b/src/_vmprof.c @@ -393,7 +393,7 @@ insert_real_time_thread(PyObject *module, PyObject * noargs) { } vmprof_aquire_lock(); - thread_count = insert_thread(pthread_self(), -1); + thread_count = insert_thread(GET_THREAD_ID(), -1); vmprof_release_lock(); return PyLong_FromSsize_t(thread_count); @@ -414,7 +414,7 @@ remove_real_time_thread(PyObject *module, PyObject * noargs) { } vmprof_aquire_lock(); - thread_count = remove_thread(pthread_self(), -1); + thread_count = remove_thread(GET_THREAD_ID(), -1); vmprof_release_lock(); return PyLong_FromSsize_t(thread_count); diff --git a/src/vmprof_common.c b/src/vmprof_common.c index d81b9119..eb64d51a 100644 --- a/src/vmprof_common.c +++ b/src/vmprof_common.c @@ -28,7 +28,7 @@ static long profile_interval_usec = 0; #ifdef VMPROF_UNIX static int signal_type = SIGPROF; static int itimer_type = ITIMER_PROF; -static pthread_t *threads = NULL; +static THREAD_ID *threads = NULL; static size_t threads_size = 0; static size_t thread_count = 0; static size_t threads_size_step = 8; @@ -221,19 +221,19 @@ intptr_t vmprof_get_traceback(void *stack, void *ucontext, #ifdef VMPROF_UNIX -ssize_t search_thread(pthread_t tid, ssize_t i) +ssize_t search_thread(THREAD_ID tid, ssize_t i) { if (i < 0) i = 0; while ((size_t)i < thread_count) { - if (pthread_equal(threads[i], tid)) + if (THREAD_EQUALS(threads[i], tid)) return i; i++; } return -1; } -ssize_t insert_thread(pthread_t tid, ssize_t i) +ssize_t insert_thread(THREAD_ID tid, ssize_t i) { assert(signal_type == SIGALRM); i = search_thread(tid, i); @@ -241,15 +241,15 @@ ssize_t insert_thread(pthread_t tid, ssize_t i) return -1; if (thread_count == threads_size) { threads_size += threads_size_step; - threads = realloc(threads, sizeof(pid_t) * threads_size); + threads = realloc(threads, sizeof(THREAD_ID) * threads_size); assert(threads != NULL); - memset(threads + thread_count, 0, sizeof(pid_t) * threads_size_step); + memset(threads + thread_count, 0, sizeof(THREAD_ID) * threads_size_step); } threads[thread_count++] = tid; return thread_count; } -ssize_t remove_thread(pthread_t tid, ssize_t i) +ssize_t remove_thread(THREAD_ID tid, ssize_t i) { assert(signal_type == SIGALRM); if (thread_count == 0) @@ -280,13 +280,14 @@ int broadcast_signal_for_threads(void) { int done = 1; size_t i = 0; - pthread_t self = pthread_self(); - pthread_t tid; + THREAD_ID self = GET_THREAD_ID(); + THREAD_ID tid; + pid_t pid = getpid(); while (i < thread_count) { tid = threads[i]; - if (pthread_equal(tid, self)) { + if (THREAD_EQUALS(tid, self)) { done = 0; - } else if (pthread_kill(tid, SIGALRM)) { + } else if (THREAD_SIGNAL(pid, tid, SIGALRM)) { remove_thread(tid, i); } i++; diff --git a/src/vmprof_common.h b/src/vmprof_common.h index 9f55f796..5d496539 100644 --- a/src/vmprof_common.h +++ b/src/vmprof_common.h @@ -21,15 +21,31 @@ #ifdef VMPROF_LINUX #include +#define THREAD_ID pid_t +#define GET_THREAD_ID() ((pid_t) syscall(SYS_gettid)) +#define THREAD_EQUALS(thread_one, thread_two) (thread_one == thread_two) +#define THREAD_SIGNAL(pid, tid, signal) syscall(SYS_tgkill, pid, tid, signal) +#else +#ifdef VMPROF_UNIX +#define THREAD_ID pthread_t +#define GET_THREAD_ID() ((pthread_t) pthread_self()) +#define THREAD_EQUALS(thread_one, thread_two) pthread_equal(thread_one, thread_two) +#define THREAD_SIGNAL(pid, tid, signal) pthread_kill(tid, signal) +#endif #endif #define MAX_FUNC_NAME 1024 +#ifdef VMPROF_LINUX +#else +#define THREAD_ID_TYPE +#endif + #ifdef VMPROF_UNIX -ssize_t search_thread(pthread_t tid, ssize_t i); -ssize_t insert_thread(pthread_t tid, ssize_t i); -ssize_t remove_thread(pthread_t tid, ssize_t i); +ssize_t search_thread(THREAD_ID tid, ssize_t i); +ssize_t insert_thread(THREAD_ID tid, ssize_t i); +ssize_t remove_thread(THREAD_ID tid, ssize_t i); ssize_t remove_threads(void); #endif diff --git a/src/vmprof_unix.c b/src/vmprof_unix.c index 1a85a10c..766e630d 100644 --- a/src/vmprof_unix.c +++ b/src/vmprof_unix.c @@ -359,7 +359,7 @@ int vmprof_enable(int memory, int native, int real_time) if (memory && setup_rss() == -1) goto error; #if VMPROF_UNIX - if (real_time && insert_thread(pthread_self(), -1) == -1) + if (real_time && insert_thread(GET_THREAD_ID(), -1) == -1) goto error; #endif if (install_pthread_atfork_hooks() == -1) diff --git a/vmprof/stats.py b/vmprof/stats.py index ee81f18e..2eb16a67 100644 --- a/vmprof/stats.py +++ b/vmprof/stats.py @@ -76,6 +76,18 @@ def generate_top(self): self.functions[addr] = self.functions.get(addr, 0) + 1 current_iter[addr] = None + def all_profile(self): + all_functions = {} + for profile in self.profiles: + for i, addr in enumerate(profile[0]): + if self.profile_lines and i % 2 == 1: + # this entry in the profile is a negative number indicating a line + assert addr <= 0 + continue + else: + all_functions[addr] = all_functions.get(addr, 0) + 1 + return [(self._get_name(k), v) for (k, v) in six.iteritems(all_functions)] + def top_profile(self): return [(self._get_name(k), v) for (k, v) in six.iteritems(self.functions)] diff --git a/vmprof/test/test_run.py b/vmprof/test/test_run.py index 29455978..69ff93e2 100644 --- a/vmprof/test/test_run.py +++ b/vmprof/test/test_run.py @@ -79,15 +79,33 @@ def function_bar(): def functime_foo(t=0.05, insert=False): + if PY3K: + from threading import get_ident + else: + from thread import get_ident + thread_id = get_ident() if (insert): - vmprof.insert_real_time_thread() - return time.sleep(t) + thread_count = vmprof.insert_real_time_thread() + else: + thread_count = -2 + sys.stderr.writelines("foo:%i:%i\n" % (thread_id, thread_count)) + time.sleep(t) + return def functime_bar(t=0.05, remove=False): + if PY3K: + from threading import get_ident + else: + from thread import get_ident + thread_id = get_ident() if (remove): - vmprof.remove_real_time_thread() - return time.sleep(t) + thread_count = vmprof.remove_real_time_thread() + else: + thread_count = -2 + sys.stderr.writelines("bar:%i:%i\n" % (thread_id, thread_count)) + time.sleep(t) + return foo_full_name = "py:function_foo:%d:%s" % (function_foo.__code__.co_firstlineno, @@ -255,7 +273,6 @@ def test_vmprof_real_time(): assert d[foo_time_name] > 0 -@py.test.mark.xfail() @py.test.mark.skipif("'__pypy__' in sys.builtin_module_names") @py.test.mark.skipif("sys.platform == 'win32'") @py.test.mark.parametrize("insert_foo,remove_bar", [ @@ -266,16 +283,20 @@ def test_vmprof_real_time(): ]) def test_vmprof_real_time_threaded(insert_foo, remove_bar): import threading + import pprint prof = vmprof.Profiler() wait = 0.5 thread = threading.Thread(target=functime_foo, args=[wait, insert_foo]) - with prof.measure(period=0.25, real_time=True): + with prof.measure(period=wait/5, real_time=True): thread.start() functime_bar(wait, remove_bar) thread.join() stats = prof.get_stats() tprof = stats.top_profile() + aprof = stats.all_profile() d = dict(tprof) + f = pprint.pformat(d) + '\n' + pprint.pformat(dict(aprof)) + '\n' + sys.stderr.writelines(f) assert insert_foo == (foo_time_name in d) assert remove_bar != (bar_time_name in d)