mirror of
https://github.com/python/cpython.git
synced 2025-10-21 14:12:27 +00:00
Massive performance improvement for C extension and builtin tracing code
This commit is contained in:
parent
ec6229e352
commit
d858a7763a
5 changed files with 31 additions and 97 deletions
|
@ -4,9 +4,9 @@ test_profile
|
||||||
Ordered by: standard name
|
Ordered by: standard name
|
||||||
|
|
||||||
ncalls tottime percall cumtime percall filename:lineno(function)
|
ncalls tottime percall cumtime percall filename:lineno(function)
|
||||||
12 0.000 0.000 0.012 0.001 :0(hasattr)
|
12 0.000 0.000 0.012 0.001 :0(<built-in function hasattr>)
|
||||||
8 0.000 0.000 0.000 0.000 :0(range)
|
8 0.000 0.000 0.000 0.000 :0(<built-in function range>)
|
||||||
1 0.000 0.000 0.000 0.000 :0(setprofile)
|
1 0.000 0.000 0.000 0.000 :0(<built-in function setprofile>)
|
||||||
1 0.000 0.000 1.000 1.000 <string>:1(?)
|
1 0.000 0.000 1.000 1.000 <string>:1(?)
|
||||||
0 0.000 0.000 profile:0(profiler)
|
0 0.000 0.000 profile:0(profiler)
|
||||||
1 0.000 0.000 1.000 1.000 profile:0(testfunc())
|
1 0.000 0.000 1.000 1.000 profile:0(testfunc())
|
||||||
|
|
|
@ -3438,47 +3438,33 @@ err_args(PyObject *func, int flags, int nargs)
|
||||||
nargs);
|
nargs);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WITH_C_PROF
|
#define C_TRACE(call) \
|
||||||
#define BEGIN_C_TRACE \
|
if (tstate->use_tracing && tstate->c_profilefunc) { \
|
||||||
if (tstate->use_tracing) { \
|
if (call_trace(tstate->c_profilefunc, \
|
||||||
|
tstate->c_profileobj, \
|
||||||
|
tstate->frame, PyTrace_C_CALL, \
|
||||||
|
func)) \
|
||||||
|
{ return NULL; } \
|
||||||
|
call; \
|
||||||
if (tstate->c_profilefunc != NULL) { \
|
if (tstate->c_profilefunc != NULL) { \
|
||||||
PyObject *func_name = \
|
if (x == NULL) { \
|
||||||
PyString_FromString (((PyCFunctionObject *) \
|
if (call_trace (tstate->c_profilefunc, \
|
||||||
func)->m_ml->ml_name); \
|
tstate->c_profileobj, \
|
||||||
are_tracing = 1; \
|
tstate->frame, PyTrace_C_EXCEPTION, \
|
||||||
if (call_trace(tstate->c_profilefunc, \
|
func)) \
|
||||||
tstate->c_profileobj, \
|
{ return NULL; } \
|
||||||
tstate->frame, PyTrace_C_CALL, \
|
} else { \
|
||||||
func_name)) \
|
if (call_trace(tstate->c_profilefunc, \
|
||||||
{ return NULL; } \
|
tstate->c_profileobj, \
|
||||||
Py_DECREF (func_name); \
|
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 *
|
static PyObject *
|
||||||
call_function(PyObject ***pp_stack, int oparg
|
call_function(PyObject ***pp_stack, int oparg
|
||||||
#ifdef WITH_TSC
|
#ifdef WITH_TSC
|
||||||
|
@ -3493,30 +3479,22 @@ call_function(PyObject ***pp_stack, int oparg
|
||||||
PyObject *func = *pfunc;
|
PyObject *func = *pfunc;
|
||||||
PyObject *x, *w;
|
PyObject *x, *w;
|
||||||
|
|
||||||
#ifdef WITH_C_PROF
|
|
||||||
int are_tracing = 0;
|
|
||||||
PyThreadState *tstate = PyThreadState_GET();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Always dispatch PyCFunction first, because these are
|
/* Always dispatch PyCFunction first, because these are
|
||||||
presumed to be the most frequent callable object.
|
presumed to be the most frequent callable object.
|
||||||
*/
|
*/
|
||||||
if (PyCFunction_Check(func) && nk == 0) {
|
if (PyCFunction_Check(func) && nk == 0) {
|
||||||
int flags = PyCFunction_GET_FLAGS(func);
|
int flags = PyCFunction_GET_FLAGS(func);
|
||||||
PCALL(PCALL_CFUNCTION);
|
PCALL(PCALL_CFUNCTION);
|
||||||
|
PyThreadState *tstate = PyThreadState_GET();
|
||||||
if (flags & (METH_NOARGS | METH_O)) {
|
if (flags & (METH_NOARGS | METH_O)) {
|
||||||
PyCFunction meth = PyCFunction_GET_FUNCTION(func);
|
PyCFunction meth = PyCFunction_GET_FUNCTION(func);
|
||||||
PyObject *self = PyCFunction_GET_SELF(func);
|
PyObject *self = PyCFunction_GET_SELF(func);
|
||||||
if (flags & METH_NOARGS && na == 0) {
|
if (flags & METH_NOARGS && na == 0) {
|
||||||
BEGIN_C_TRACE
|
C_TRACE(x=(*meth)(self,NULL));
|
||||||
x = (*meth)(self, NULL);
|
|
||||||
END_C_TRACE
|
|
||||||
}
|
}
|
||||||
else if (flags & METH_O && na == 1) {
|
else if (flags & METH_O && na == 1) {
|
||||||
PyObject *arg = EXT_POP(*pp_stack);
|
PyObject *arg = EXT_POP(*pp_stack);
|
||||||
BEGIN_C_TRACE
|
C_TRACE(x=(*meth)(self,arg));
|
||||||
x = (*meth)(self, arg);
|
|
||||||
END_C_TRACE
|
|
||||||
Py_DECREF(arg);
|
Py_DECREF(arg);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -3527,15 +3505,13 @@ call_function(PyObject ***pp_stack, int oparg
|
||||||
else {
|
else {
|
||||||
PyObject *callargs;
|
PyObject *callargs;
|
||||||
callargs = load_args(pp_stack, na);
|
callargs = load_args(pp_stack, na);
|
||||||
BEGIN_C_TRACE
|
|
||||||
#ifdef WITH_TSC
|
#ifdef WITH_TSC
|
||||||
rdtscll(*pintr0);
|
rdtscll(*pintr0);
|
||||||
#endif
|
#endif
|
||||||
x = PyCFunction_Call(func, callargs, NULL);
|
C_TRACE(x=PyCFunction_Call(func,callargs,NULL));
|
||||||
#ifdef WITH_TSC
|
#ifdef WITH_TSC
|
||||||
rdtscll(*pintr1);
|
rdtscll(*pintr1);
|
||||||
#endif
|
#endif
|
||||||
END_C_TRACE
|
|
||||||
Py_XDECREF(callargs);
|
Py_XDECREF(callargs);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
28
configure
vendored
28
configure
vendored
|
@ -1,5 +1,5 @@
|
||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
# From configure.in Revision: 1.458 .
|
# From configure.in Revision: 1.459 .
|
||||||
# Guess values for system-dependent variables and create Makefiles.
|
# Guess values for system-dependent variables and create Makefiles.
|
||||||
# Generated by GNU Autoconf 2.59 for python 2.4.
|
# Generated by GNU Autoconf 2.59 for python 2.4.
|
||||||
#
|
#
|
||||||
|
@ -869,7 +869,6 @@ Optional Packages:
|
||||||
deprecated; use --with(out)-threads
|
deprecated; use --with(out)-threads
|
||||||
--with-pth use GNU pth threading libraries
|
--with-pth use GNU pth threading libraries
|
||||||
--with(out)-doc-strings disable/enable documentation strings
|
--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)-tsc enable/disable timestamp counter profile
|
||||||
--with(out)-pymalloc disable/enable specialized mallocs
|
--with(out)-pymalloc disable/enable specialized mallocs
|
||||||
--with-wctype-functions use wctype.h functions
|
--with-wctype-functions use wctype.h functions
|
||||||
|
@ -13030,31 +13029,6 @@ fi
|
||||||
echo "$as_me:$LINENO: result: $with_doc_strings" >&5
|
echo "$as_me:$LINENO: result: $with_doc_strings" >&5
|
||||||
echo "${ECHO_T}$with_doc_strings" >&6
|
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
|
# Check for Python-specific malloc support
|
||||||
echo "$as_me:$LINENO: checking for --with-tsc" >&5
|
echo "$as_me:$LINENO: checking for --with-tsc" >&5
|
||||||
echo $ECHO_N "checking for --with-tsc... $ECHO_C" >&6
|
echo $ECHO_N "checking for --with-tsc... $ECHO_C" >&6
|
||||||
|
|
13
configure.in
13
configure.in
|
@ -1946,19 +1946,6 @@ then
|
||||||
fi
|
fi
|
||||||
AC_MSG_RESULT($with_doc_strings)
|
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
|
# Check for Python-specific malloc support
|
||||||
AC_MSG_CHECKING(for --with-tsc)
|
AC_MSG_CHECKING(for --with-tsc)
|
||||||
AC_ARG_WITH(tsc,
|
AC_ARG_WITH(tsc,
|
||||||
|
|
|
@ -759,9 +759,6 @@
|
||||||
/* Define if WINDOW in curses.h offers a field _flags. */
|
/* Define if WINDOW in curses.h offers a field _flags. */
|
||||||
#undef WINDOW_HAS_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 */
|
/* Define if you want documentation strings in extension modules */
|
||||||
#undef WITH_DOC_STRINGS
|
#undef WITH_DOC_STRINGS
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue