A bit faster access to module attributes
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)); }
Python module calls PyObject_GenericGetAttr/PyObject_GenericSetAttr pair to do attribute lookup. (moduleobject.c,object.c)
This was introduced at the time when modules were made subclassable; before then, it looked pretty much like what you propose.
IMO it adds unnecessary overhead, and could be replaced with a bit simplified functions.
Have you found any situation where this particular operation was time-critical? I believe (without thinking it through in detail) that the generic getattr/setattr routines are required in order to support subclassing of modules, which people use. So I think your suggestion cannot work, and I also think it is unnecessary, so I don't believe it is worth the bother. --Guido van Rossum (home page: http://www.python.org/~guido/)
participants (2)
-
Guido van Rossum
-
Wiktor Sadowski