[Python-checkins] python/dist/src/Python ceval.c, 2.398,
2.399 pystate.c, 2.30, 2.31 sysmodule.c, 2.123, 2.124
loewis at users.sourceforge.net
loewis at users.sourceforge.net
Tue Jun 8 04:17:47 EDT 2004
Update of /cvsroot/python/python/dist/src/Python
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv29830/Python
Modified Files:
ceval.c pystate.c sysmodule.c
Log Message:
Patch #510695: Add TSC profiling for the VM.
Index: ceval.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/ceval.c,v
retrieving revision 2.398
retrieving revision 2.399
diff -C2 -d -r2.398 -r2.399
*** ceval.c 5 Jun 2004 06:16:22 -0000 2.398
--- ceval.c 8 Jun 2004 08:17:43 -0000 2.399
***************
*** 18,21 ****
--- 18,41 ----
#include <ctype.h>
+ #ifdef WITH_TSC
+ #include <asm/msr.h>
+
+ typedef unsigned long long uint64;
+
+ void dump_tsc(int opcode, int ticked, uint64 inst0, uint64 inst1,
+ uint64 loop0, uint64 loop1, uint64 intr0, uint64 intr1)
+ {
+ uint64 intr, inst, loop;
+ PyThreadState *tstate = PyThreadState_Get();
+ if (!tstate->interp->tscdump)
+ return;
+ intr = intr1 - intr0;
+ inst = inst1 - inst0 - intr;
+ loop = loop1 - loop0 - intr;
+ fprintf(stderr, "opcode=%03d t=%d inst=%06lld loop=%06lld\n",
+ opcode, ticked, inst, loop);
+ }
+ #endif
+
/* Turn this on if your compiler chokes on the big switch: */
/* #define CASE_TOO_BIG 1 */
***************
*** 31,35 ****
--- 51,59 ----
/* Forward declarations */
static PyObject *eval_frame(PyFrameObject *);
+ #ifdef WITH_TSC
+ static PyObject *call_function(PyObject ***, int, uint64*, uint64*);
+ #else
static PyObject *call_function(PyObject ***, int);
+ #endif
static PyObject *fast_function(PyObject *, PyObject ***, int, int, int);
static PyObject *do_call(PyObject *, PyObject ***, int, int);
***************
*** 486,489 ****
--- 510,551 ----
#endif
+ #ifdef WITH_TSC
+ /* Use Pentium timestamp counter to mark certain events:
+ inst0 -- beginning of switch statement for opcode dispatch
+ inst1 -- end of switch statement (may be skipped)
+ loop0 -- the top of the mainloop
+ loop1 -- place where control returns again to top of mainloop
+ (may be skipped)
+ intr1 -- beginning of long interruption
+ intr2 -- end of long interruption
+
+ Many opcodes call out to helper C functions. In some cases, the
+ time in those functions should be counted towards the time for the
+ opcode, but not in all cases. For example, a CALL_FUNCTION opcode
+ calls another Python function; there's no point in charge all the
+ bytecode executed by the called function to the caller.
+
+ It's hard to make a useful judgement statically. In the presence
+ of operator overloading, it's impossible to tell if a call will
+ execute new Python code or not.
+
+ It's a case-by-case judgement. I'll use intr1 for the following
+ cases:
+
+ EXEC_STMT
+ IMPORT_STAR
+ IMPORT_FROM
+ CALL_FUNCTION (and friends)
+
+ */
+ uint64 inst0, inst1, loop0, loop1, intr0 = 0, intr1 = 0;
+ int ticked = 0;
+
+ rdtscll(inst0);
+ rdtscll(inst1);
+ rdtscll(loop0);
+ rdtscll(loop1);
+ #endif
+
/* Code access macros */
***************
*** 644,647 ****
--- 706,726 ----
for (;;) {
+ #ifdef WITH_TSC
+ if (inst1 == 0) {
+ /* Almost surely, the opcode executed a break
+ or a continue, preventing inst1 from being set
+ on the way out of the loop.
+ */
+ rdtscll(inst1);
+ loop1 = inst1;
+ }
+ dump_tsc(opcode, ticked, inst0, inst1, loop0, loop1,
+ intr0, intr1);
+ ticked = 0;
+ inst1 = 0;
+ intr0 = 0;
+ intr1 = 0;
+ rdtscll(loop0);
+ #endif
assert(stack_pointer >= f->f_valuestack); /* else underflow */
assert(STACK_LEVEL() <= f->f_stacksize); /* else overflow */
***************
*** 663,666 ****
--- 742,748 ----
_Py_Ticker = _Py_CheckInterval;
tstate->tick_counter++;
+ #ifdef WITH_TSC
+ ticked = 1;
+ #endif
if (things_to_do) {
if (Py_MakePendingCalls() < 0) {
***************
*** 753,756 ****
--- 835,841 ----
/* Main switch on opcode */
+ #ifdef WITH_TSC
+ rdtscll(inst0);
+ #endif
switch (opcode) {
***************
*** 1494,1498 ****
--- 1579,1589 ----
u = THIRD();
STACKADJ(-3);
+ #ifdef WITH_TSC
+ rdtscll(intr0);
+ #endif
err = exec_statement(f, u, v, w);
+ #ifdef WITH_TSC
+ rdtscll(intr1);
+ #endif
Py_DECREF(u);
Py_DECREF(v);
***************
*** 1856,1860 ****
--- 1947,1957 ----
break;
}
+ #ifdef WITH_TSC
+ rdtscll(intr0);
+ #endif
x = PyEval_CallObject(x, w);
+ #ifdef WITH_TSC
+ rdtscll(intr1);
+ #endif
Py_DECREF(w);
SET_TOP(x);
***************
*** 1870,1874 ****
--- 1967,1977 ----
break;
}
+ #ifdef WITH_TSC
+ rdtscll(intr0);
+ #endif
err = import_all_from(x, v);
+ #ifdef WITH_TSC
+ rdtscll(intr1);
+ #endif
PyFrame_LocalsToFast(f, 0);
Py_DECREF(v);
***************
*** 1879,1883 ****
--- 1982,1992 ----
w = GETITEM(names, oparg);
v = TOP();
+ #ifdef WITH_TSC
+ rdtscll(intr0);
+ #endif
x = import_from(v, w);
+ #ifdef WITH_TSC
+ rdtscll(intr1);
+ #endif
PUSH(x);
if (x != NULL) continue;
***************
*** 1988,1992 ****
--- 2097,2105 ----
case CALL_FUNCTION:
PCALL(PCALL_ALL);
+ #ifdef WITH_TSC
+ x = call_function(&stack_pointer, oparg, &intr0, &intr1);
+ #else
x = call_function(&stack_pointer, oparg);
+ #endif
PUSH(x);
if (x != NULL)
***************
*** 2023,2027 ****
--- 2136,2146 ----
} else
Py_INCREF(func);
+ #ifdef WITH_TSC
+ rdtscll(intr0);
+ #endif
x = ext_do_call(func, &stack_pointer, flags, na, nk);
+ #ifdef WITH_TSC
+ rdtscll(intr1);
+ #endif
Py_DECREF(func);
***************
*** 2135,2138 ****
--- 2254,2261 ----
on_error:
+ #ifdef WITH_TSC
+ rdtscll(inst1);
+ #endif
+
/* Quickly continue if no error occurred */
***************
*** 2144,2150 ****
fprintf(stderr,
"XXX undetected error\n");
! else
#endif
continue; /* Normal, fast path */
}
why = WHY_EXCEPTION;
--- 2267,2279 ----
fprintf(stderr,
"XXX undetected error\n");
! else {
! #endif
! #ifdef WITH_TSC
! rdtscll(loop1);
#endif
continue; /* Normal, fast path */
+ #ifdef CHECKEXC
+ }
+ #endif
}
why = WHY_EXCEPTION;
***************
*** 2261,2264 ****
--- 2390,2396 ----
if (why != WHY_NOT)
break;
+ #ifdef WITH_TSC
+ rdtscll(loop1);
+ #endif
} /* main loop */
***************
*** 3332,3336 ****
static PyObject *
! call_function(PyObject ***pp_stack, int oparg)
{
int na = oparg & 0xff;
--- 3464,3472 ----
static PyObject *
! call_function(PyObject ***pp_stack, int oparg
! #ifdef WITH_TSC
! , uint64* pintr0, uint64* pintr1
! #endif
! )
{
int na = oparg & 0xff;
***************
*** 3375,3379 ****
--- 3511,3521 ----
callargs = load_args(pp_stack, na);
BEGIN_C_TRACE
+ #ifdef WITH_TSC
+ rdtscll(*pintr0);
+ #endif
x = PyCFunction_Call(func, callargs, NULL);
+ #ifdef WITH_TSC
+ rdtscll(*pintr1);
+ #endif
END_C_TRACE
Py_XDECREF(callargs);
***************
*** 3394,3401 ****
--- 3536,3549 ----
} else
Py_INCREF(func);
+ #ifdef WITH_TSC
+ rdtscll(*pintr0);
+ #endif
if (PyFunction_Check(func))
x = fast_function(func, pp_stack, n, na, nk);
else
x = do_call(func, pp_stack, na, nk);
+ #ifdef WITH_TSC
+ rdtscll(*pintr1);
+ #endif
Py_DECREF(func);
}
Index: pystate.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/pystate.c,v
retrieving revision 2.30
retrieving revision 2.31
diff -C2 -d -r2.30 -r2.31
*** pystate.c 24 Mar 2004 22:22:12 -0000 2.30
--- pystate.c 8 Jun 2004 08:17:44 -0000 2.31
***************
*** 60,63 ****
--- 60,66 ----
#endif
#endif
+ #ifdef WITH_TSC
+ interp->tscdump = 0;
+ #endif
HEAD_LOCK();
Index: sysmodule.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/sysmodule.c,v
retrieving revision 2.123
retrieving revision 2.124
diff -C2 -d -r2.123 -r2.124
*** sysmodule.c 24 Mar 2004 22:22:12 -0000 2.123
--- sysmodule.c 8 Jun 2004 08:17:44 -0000 2.124
***************
*** 443,446 ****
--- 443,473 ----
);
+ #ifdef WITH_TSC
+ static PyObject *
+ sys_settscdump(PyObject *self, PyObject *args)
+ {
+ int bool;
+ PyThreadState *tstate = PyThreadState_Get();
+
+ if (!PyArg_ParseTuple(args, "i:settscdump", &bool))
+ return NULL;
+ if (bool)
+ tstate->interp->tscdump = 1;
+ else
+ tstate->interp->tscdump = 0;
+ Py_INCREF(Py_None);
+ return Py_None;
+
+ }
+
+ PyDoc_STRVAR(settscdump_doc,
+ "settscdump(bool)\n\
+ \n\
+ If true, tell the Python interpreter to dump VM measurements to\n\
+ stderr. If false, turn off dump. The measurements are based on the\n\
+ Pentium time-stamp counter."
+ );
+ #endif TSC
+
static PyObject *
sys_setrecursionlimit(PyObject *self, PyObject *args)
***************
*** 744,747 ****
--- 771,777 ----
{"setrecursionlimit", sys_setrecursionlimit, METH_VARARGS,
setrecursionlimit_doc},
+ #ifdef WITH_TSC
+ {"settscdump", sys_settscdump, METH_VARARGS, settscdump_doc},
+ #endif
{"settrace", sys_settrace, METH_O, settrace_doc},
{"call_tracing", sys_call_tracing, METH_VARARGS, call_tracing_doc},
More information about the Python-checkins
mailing list