summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2001-10-03 12:09:30 (GMT)
committerGuido van Rossum <guido@python.org>2001-10-03 12:09:30 (GMT)
commitf4593e0b657a29f93a74a578cb4d78aafdf384ea (patch)
tree7c8e2ba062e01c9100c05dd7593be2cf639240b4 /Objects
parent1b0e5490c566826188175b03458e123c043a7991 (diff)
downloadcpython-f4593e0b657a29f93a74a578cb4d78aafdf384ea.zip
cpython-f4593e0b657a29f93a74a578cb4d78aafdf384ea.tar.gz
cpython-f4593e0b657a29f93a74a578cb4d78aafdf384ea.tar.bz2
*EXPERIMENTAL* speedup of slot_sq_item. This sped up the following
test dramatically: class T(tuple): __dynamic__ = 1 t = T(range(1000)) for i in range(1000): tt = tuple(t) The speedup was about 5x compared to the previous state of CVS (1.7 vs. 8.8, in arbitrary time units). But it's still more than twice as slow as as the same test with __dynamic__ = 0 (0.8). I'm not sure that I really want to go through the trouble of this kind of speedup for every slot. Even doing it just for the most popular slots will be a major effort (the new slot_sq_item is 40+ lines, while the old one was one line with a powerful macro -- unfortunately the speedup comes from expanding the macro and doing things in a way specific to the slot signature). An alternative that I'm currently considering is sketched in PLAN.txt: trap setattr on type objects. But this will require keeping track of all derived types using weak references.
Diffstat (limited to 'Objects')
-rw-r--r--Objects/descrobject.c34
-rw-r--r--Objects/typeobject.c68
2 files changed, 62 insertions, 40 deletions
diff --git a/Objects/descrobject.c b/Objects/descrobject.c
index 3a65902..1d525da 100644
--- a/Objects/descrobject.c
+++ b/Objects/descrobject.c
@@ -3,38 +3,6 @@
#include "Python.h"
#include "structmember.h" /* Why is this not included in Python.h? */
-/* Various kinds of descriptor objects */
-
-#define COMMON \
- PyObject_HEAD \
- PyTypeObject *d_type; \
- PyObject *d_name
-
-typedef struct {
- COMMON;
-} PyDescrObject;
-
-typedef struct {
- COMMON;
- PyMethodDef *d_method;
-} PyMethodDescrObject;
-
-typedef struct {
- COMMON;
- PyMemberDef *d_member;
-} PyMemberDescrObject;
-
-typedef struct {
- COMMON;
- PyGetSetDef *d_getset;
-} PyGetSetDescrObject;
-
-typedef struct {
- COMMON;
- struct wrapperbase *d_base;
- void *d_wrapped; /* This can be any function pointer */
-} PyWrapperDescrObject;
-
static void
descr_dealloc(PyDescrObject *descr)
{
@@ -481,7 +449,7 @@ static PyTypeObject PyGetSetDescr_Type = {
(descrsetfunc)getset_set, /* tp_descr_set */
};
-static PyTypeObject PyWrapperDescr_Type = {
+PyTypeObject PyWrapperDescr_Type = {
PyObject_HEAD_INIT(&PyType_Type)
0,
"wrapper_descriptor",
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index a681d33..d976945 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -2113,12 +2113,16 @@ wrap_sq_item(PyObject *self, PyObject *args, void *wrapped)
PyObject *arg;
int i;
- if (!PyArg_ParseTuple(args, "O", &arg))
- return NULL;
- i = getindex(self, arg);
- if (i == -1 && PyErr_Occurred())
- return NULL;
- return (*func)(self, i);
+ if (PyTuple_GET_SIZE(args) == 1) {
+ arg = PyTuple_GET_ITEM(args, 0);
+ i = getindex(self, arg);
+ if (i == -1 && PyErr_Occurred())
+ return NULL;
+ return (*func)(self, i);
+ }
+ PyArg_ParseTuple(args, "O", &arg);
+ assert(PyErr_Occurred());
+ return NULL;
}
static struct wrapperbase tab_getitem_int[] = {
@@ -2825,7 +2829,57 @@ slot_sq_length(PyObject *self)
SLOT1(slot_sq_concat, "__add__", PyObject *, "O")
SLOT1(slot_sq_repeat, "__mul__", int, "i")
-SLOT1(slot_sq_item, "__getitem__", int, "i")
+
+/* Super-optimized version of slot_sq_item.
+ Other slots could do the same... */
+static PyObject *
+slot_sq_item(PyObject *self, int i)
+{
+ static PyObject *getitem_str;
+ PyObject *func, *args = NULL, *ival = NULL, *retval = NULL;
+ descrgetfunc f;
+
+ if (getitem_str == NULL) {
+ getitem_str = PyString_InternFromString("__getitem__");
+ if (getitem_str == NULL)
+ return NULL;
+ }
+ func = _PyType_Lookup(self->ob_type, getitem_str);
+ if (func != NULL) {
+ if (func->ob_type == &PyWrapperDescr_Type) {
+ PyWrapperDescrObject *wrapper =
+ (PyWrapperDescrObject *)func;
+ if (wrapper->d_base->wrapper == wrap_sq_item) {
+ intargfunc f;
+ f = (intargfunc)(wrapper->d_wrapped);
+ return f(self, i);
+ }
+ }
+ if ((f = func->ob_type->tp_descr_get) == NULL)
+ Py_INCREF(func);
+ else
+ func = f(func, self, (PyObject *)(self->ob_type));
+ ival = PyInt_FromLong(i);
+ if (ival != NULL) {
+ args = PyTuple_New(1);
+ if (args != NULL) {
+ PyTuple_SET_ITEM(args, 0, ival);
+ retval = PyObject_Call(func, args, NULL);
+ Py_XDECREF(args);
+ Py_XDECREF(func);
+ return retval;
+ }
+ }
+ }
+ else {
+ PyErr_SetObject(PyExc_AttributeError, getitem_str);
+ }
+ Py_XDECREF(args);
+ Py_XDECREF(ival);
+ Py_XDECREF(func);
+ return NULL;
+}
+
SLOT2(slot_sq_slice, "__getslice__", int, int, "ii")
static int