[Python-Dev] A bit faster access to module attributes
Wiktor Sadowski
Wiktor Sadowski" <art@wiktorsadowski.com
Tue, 1 Jul 2003 03:40:23 +0200
Python module calls PyObject_GenericGetAttr/PyObject_GenericSetAttr pair
to do attribute lookup. (moduleobject.c,object.c)
IMO it adds unnecessary overhead, and could be replaced with a bit
simplified functions.
[1] To get an object's dictionary _PyObject_GetDictPtr function is used
(inlined in PyObject_GenericGetAttr).
But in module case we can get the dictionary without any call:
PyObject *dict = ((PyModuleObject *)obj)->md_dict;
[2] If module(tp)->tp_dict == NULL PyType_Ready is called in
PyObject_GenericGetAttr.
Well , I am not sure if all this stuff added to module type with
PyType_Ready
is really necessary but instead of calling _PyType_Lookup machinery a
simple:
if (strcmp(PyString_AS_STRING(name/*attr*/),"__dict__")==0)
(+ PyErr_SetString(PyExc_TypeError, "readonly attribute") for setattr
function)
could be used to access readonly module "__dict__" attribute.
The solution I am proposing is probably less elegant than
PyObject_GenericGetAttr/PyObject_GenericSetAttr
but if it could speed up Python a bit ?
If someone would like to test such modified modules,
binaries for Windows of my small C extension - modeler.pyd are available at:
http://www.wiktorsadowski.com/Python
Importing modeler will replace module
tp_getattro/ tp_setattro with new functions,
and will enable faster access to modules' attributes.
(if no other modeler features are used)
Regards
Wiktor Sadowski
___________________________________________________________________
A new getattr for module tp_getattro could look like this:
(the settattr could be simplified as well)
PyObject *
PyObject_ModuleGetAttr(PyObject *obj, PyObject *name)
{
PyObject *res = NULL;
PyTypeObject *tp = obj->ob_type;
PyObject *dict = ((PyModuleObject *)obj)->md_dict;
/*string check stuff - no changes*/
if (dict == NULL) { /* it shouldn't happen! */
((PyModuleObject *)obj)->md_dict=Py_DictNew();/*?*/
}
if (strcmp(PyString_AS_STRING(name),"__dict__")==0){
Py_INCREF(dict);
return dict;
}
res = PyDict_GetItem(dict, name);
if (res != NULL) {
Py_INCREF(res);
Py_XDECREF(name);
return res;
}
PyErr_Format(PyExc_AttributeError,
"'%.50s' object has no attribute '%.400s'",
tp->tp_name, PyString_AS_STRING(name));
}