From d858a7763ae31148451b79b7f258f34ddc5a11b0 Mon Sep 17 00:00:00 2001 From: Nicholas Bastin Date: Fri, 25 Jun 2004 23:31:06 +0000 Subject: Massive performance improvement for C extension and builtin tracing code --- Lib/test/output/test_profile | 6 ++-- Python/ceval.c | 78 +++++++++++++++----------------------------- configure | 28 +--------------- configure.in | 13 -------- pyconfig.h.in | 3 -- 5 files changed, 31 insertions(+), 97 deletions(-) diff --git a/Lib/test/output/test_profile b/Lib/test/output/test_profile index b46bb6a..baa2509 100644 --- a/Lib/test/output/test_profile +++ b/Lib/test/output/test_profile @@ -4,9 +4,9 @@ test_profile Ordered by: standard name ncalls tottime percall cumtime percall filename:lineno(function) - 12 0.000 0.000 0.012 0.001 :0(hasattr) - 8 0.000 0.000 0.000 0.000 :0(range) - 1 0.000 0.000 0.000 0.000 :0(setprofile) + 12 0.000 0.000 0.012 0.001 :0() + 8 0.000 0.000 0.000 0.000 :0() + 1 0.000 0.000 0.000 0.000 :0() 1 0.000 0.000 1.000 1.000 :1(?) 0 0.000 0.000 profile:0(profiler) 1 0.000 0.000 1.000 1.000 profile:0(testfunc()) diff --git a/Python/ceval.c b/Python/ceval.c index 6f6fef6..b320f61 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3438,47 +3438,33 @@ err_args(PyObject *func, int flags, int nargs) nargs); } -#ifdef WITH_C_PROF -#define BEGIN_C_TRACE \ -if (tstate->use_tracing) { \ +#define C_TRACE(call) \ +if (tstate->use_tracing && tstate->c_profilefunc) { \ + if (call_trace(tstate->c_profilefunc, \ + tstate->c_profileobj, \ + tstate->frame, PyTrace_C_CALL, \ + func)) \ + { return NULL; } \ + call; \ if (tstate->c_profilefunc != NULL) { \ - PyObject *func_name = \ - PyString_FromString (((PyCFunctionObject *) \ - func)->m_ml->ml_name); \ - are_tracing = 1; \ - if (call_trace(tstate->c_profilefunc, \ - tstate->c_profileobj, \ - tstate->frame, PyTrace_C_CALL, \ - func_name)) \ - { return NULL; } \ - Py_DECREF (func_name); \ + if (x == NULL) { \ + if (call_trace (tstate->c_profilefunc, \ + tstate->c_profileobj, \ + tstate->frame, PyTrace_C_EXCEPTION, \ + func)) \ + { return NULL; } \ + } else { \ + if (call_trace(tstate->c_profilefunc, \ + tstate->c_profileobj, \ + tstate->frame, PyTrace_C_RETURN, \ + func)) \ + { return NULL; } \ } \ + } \ +} else { \ + call; \ } -#define END_C_TRACE \ - if (tstate->use_tracing && are_tracing) { \ - if (tstate->c_profilefunc != NULL) { \ - if (x == NULL) { \ - if (call_trace (tstate->c_profilefunc, \ - tstate->c_profileobj, \ - tstate->frame, PyTrace_C_EXCEPTION, \ - NULL)) \ - { return NULL; } \ - } else { \ - if (call_trace(tstate->c_profilefunc, \ - tstate->c_profileobj, \ - tstate->frame, PyTrace_C_RETURN, \ - NULL)) \ - { return NULL; } \ - } \ - } \ - } -#else -#define BEGIN_C_TRACE -#define END_C_TRACE -#endif - - static PyObject * call_function(PyObject ***pp_stack, int oparg #ifdef WITH_TSC @@ -3493,30 +3479,22 @@ call_function(PyObject ***pp_stack, int oparg PyObject *func = *pfunc; PyObject *x, *w; -#ifdef WITH_C_PROF - int are_tracing = 0; - PyThreadState *tstate = PyThreadState_GET(); -#endif - /* Always dispatch PyCFunction first, because these are presumed to be the most frequent callable object. */ if (PyCFunction_Check(func) && nk == 0) { int flags = PyCFunction_GET_FLAGS(func); PCALL(PCALL_CFUNCTION); + PyThreadState *tstate = PyThreadState_GET(); if (flags & (METH_NOARGS | METH_O)) { PyCFunction meth = PyCFunction_GET_FUNCTION(func); PyObject *self = PyCFunction_GET_SELF(func); if (flags & METH_NOARGS && na == 0) { - BEGIN_C_TRACE - x = (*meth)(self, NULL); - END_C_TRACE + C_TRACE(x=(*meth)(self,NULL)); } else if (flags & METH_O && na == 1) { PyObject *arg = EXT_POP(*pp_stack); - BEGIN_C_TRACE - x = (*meth)(self, arg); - END_C_TRACE + C_TRACE(x=(*meth)(self,arg)); Py_DECREF(arg); } else { @@ -3527,15 +3505,13 @@ call_function(PyObject ***pp_stack, int oparg else { PyObject *callargs; callargs = load_args(pp_stack, na); - BEGIN_C_TRACE #ifdef WITH_TSC rdtscll(*pintr0); #endif - x = PyCFunction_Call(func, callargs, NULL); + C_TRACE(x=PyCFunction_Call(func,callargs,NULL)); #ifdef WITH_TSC rdtscll(*pintr1); #endif - END_C_TRACE Py_XDECREF(callargs); } } else { diff --git a/configure b/configure index 0c0c443..31e6541 100755 --- a/configure +++ b/configure @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.in Revision: 1.458 . +# From configure.in Revision: 1.459 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.59 for python 2.4. # @@ -869,7 +869,6 @@ Optional Packages: deprecated; use --with(out)-threads --with-pth use GNU pth threading libraries --with(out)-doc-strings disable/enable documentation strings - --with-c-profiling Enable profiling of builtins and C extension functions --with(out)-tsc enable/disable timestamp counter profile --with(out)-pymalloc disable/enable specialized mallocs --with-wctype-functions use wctype.h functions @@ -13030,31 +13029,6 @@ fi echo "$as_me:$LINENO: result: $with_doc_strings" >&5 echo "${ECHO_T}$with_doc_strings" >&6 -# Check for C call profiling support -echo "$as_me:$LINENO: checking for --with-c-profiling" >&5 -echo $ECHO_N "checking for --with-c-profiling... $ECHO_C" >&6 - -# Check whether --with-c-profiling or --without-c-profiling was given. -if test "${with_c_profiling+set}" = set; then - withval="$with_c_profiling" - -if test "$withval" != no -then - -cat >>confdefs.h <<\_ACEOF -#define WITH_C_PROF 1 -_ACEOF - - echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 -else echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi; - # Check for Python-specific malloc support echo "$as_me:$LINENO: checking for --with-tsc" >&5 echo $ECHO_N "checking for --with-tsc... $ECHO_C" >&6 diff --git a/configure.in b/configure.in index c766eb1..7e13874 100644 --- a/configure.in +++ b/configure.in @@ -1946,19 +1946,6 @@ then fi AC_MSG_RESULT($with_doc_strings) -# Check for C call profiling support -AC_MSG_CHECKING(for --with-c-profiling) -AC_ARG_WITH(c-profiling, -[ --with-c-profiling Enable profiling of builtins and C extension functions], [ -if test "$withval" != no -then - AC_DEFINE(WITH_C_PROF, 1, - [Define to enable profile hooks for C extension functions and builtins]) - AC_MSG_RESULT(yes) -else AC_MSG_RESULT(no) -fi], -[AC_MSG_RESULT(no)]) - # Check for Python-specific malloc support AC_MSG_CHECKING(for --with-tsc) AC_ARG_WITH(tsc, diff --git a/pyconfig.h.in b/pyconfig.h.in index e939c01..8cb0cff 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -759,9 +759,6 @@ /* Define if WINDOW in curses.h offers a field _flags. */ #undef WINDOW_HAS_FLAGS -/* Define to enable profile hooks for C extension functions and builtins */ -#undef WITH_C_PROF - /* Define if you want documentation strings in extension modules */ #undef WITH_DOC_STRINGS -- cgit v0.12