[Python-checkins] r68828 - in python/branches/io-c/Modules: _fileio.c _iomodule.h _textio.c

antoine.pitrou python-checkins at python.org
Wed Jan 21 00:06:33 CET 2009


Author: antoine.pitrou
Date: Wed Jan 21 00:06:33 2009
New Revision: 68828

Log:
Speed up closed checks on text IO objects. Good for a 25% speedup on small ops.



Modified:
   python/branches/io-c/Modules/_fileio.c
   python/branches/io-c/Modules/_iomodule.h
   python/branches/io-c/Modules/_textio.c

Modified: python/branches/io-c/Modules/_fileio.c
==============================================================================
--- python/branches/io-c/Modules/_fileio.c	(original)
+++ python/branches/io-c/Modules/_fileio.c	Wed Jan 21 00:06:33 2009
@@ -57,6 +57,13 @@
 
 #define PyFileIO_Check(op) (PyObject_TypeCheck((op), &PyFileIO_Type))
 
+
+int
+_PyFileIO_closed(PyObject *self)
+{
+	return ((PyFileIOObject *)self)->fd < 0;
+}
+
 /* Returns 0 on success, -1 with exception set on failure. */
 static int
 internal_close(PyFileIOObject *self)

Modified: python/branches/io-c/Modules/_iomodule.h
==============================================================================
--- python/branches/io-c/Modules/_iomodule.h	(original)
+++ python/branches/io-c/Modules/_iomodule.h	Wed Jan 21 00:06:33 2009
@@ -35,6 +35,11 @@
    is alive again. */
 extern int _PyIOBase_finalize(PyObject *self);
 
+/* Returns true if the given FileIO object is closed.
+   Doesn't check the argument type, so be careful! */
+extern int _PyFileIO_closed(PyObject *self);
+
+
 #define DEFAULT_BUFFER_SIZE (8 * 1024)  /* bytes */
 
 typedef struct {

Modified: python/branches/io-c/Modules/_textio.c
==============================================================================
--- python/branches/io-c/Modules/_textio.c	(original)
+++ python/branches/io-c/Modules/_textio.c	Wed Jan 21 00:06:33 2009
@@ -606,6 +606,9 @@
      * snapshot point.  We use this to reconstruct decoder states in tell().
      */
 
+    /* Cache raw object if it's a FileIO object */
+    PyObject *raw;
+
     PyObject *weakreflist;
     PyObject *dict;
 } PyTextIOWrapperObject;
@@ -697,7 +700,7 @@
     char *kwlist[] = {"buffer", "encoding", "errors",
                       "newline", "line_buffering",
                       NULL};
-    PyObject *buffer;
+    PyObject *buffer, *raw;
     char *encoding = NULL;
     char *errors = NULL;
     char *newline = NULL;
@@ -730,6 +733,7 @@
     Py_CLEAR(self->pending_bytes);
     Py_CLEAR(self->snapshot);
     Py_CLEAR(self->errors);
+    Py_CLEAR(self->raw);
     self->decoded_chars_used = 0;
     self->pending_bytes_count = 0;
     self->encodefunc = NULL;
@@ -871,6 +875,19 @@
 
     self->buffer = buffer;
     Py_INCREF(buffer);
+    
+    if (Py_TYPE(buffer) == &PyBufferedReader_Type ||
+        Py_TYPE(buffer) == &PyBufferedWriter_Type ||
+        Py_TYPE(buffer) == &PyBufferedRandom_Type) {
+        raw = PyObject_GetAttrString(buffer, "raw");
+        /* Cache the raw FileIO object to speed up 'closed' checks */
+        if (raw == NULL)
+            PyErr_Clear();
+        else if (Py_TYPE(raw) == &PyFileIO_Type)
+            self->raw = raw;
+        else
+            Py_DECREF(raw);
+    }
 
     res = PyObject_CallMethod(buffer, "seekable", NULL);
     if (res == NULL)
@@ -900,6 +917,7 @@
     Py_CLEAR(self->pending_bytes);
     Py_CLEAR(self->snapshot);
     Py_CLEAR(self->errors);
+    Py_CLEAR(self->raw);
     return 0;
 }
 
@@ -926,6 +944,8 @@
     Py_VISIT(self->pending_bytes);
     Py_VISIT(self->snapshot);
     Py_VISIT(self->errors);
+    Py_VISIT(self->raw);
+
     Py_VISIT(self->dict);
     return 0;
 }
@@ -942,21 +962,23 @@
 static PyObject *
 TextIOWrapper_closed_get(PyTextIOWrapperObject *self, void *context);
 
-/* This macro takes some shortcuts to make the common case faster. We could
-   specialize even more, by detecting that the underlying buffer is a 
-   BufferedObject. */
+/* This macro takes some shortcuts to make the common case faster. */
 #define CHECK_CLOSED(self) \
     do { \
         int r; \
         PyObject *_res; \
         if (Py_TYPE(self) == &PyTextIOWrapper_Type) { \
-            _res = TextIOWrapper_closed_get(self, NULL); \
-            if (_res == NULL) \
-                return NULL; \
-            r = PyObject_IsTrue(_res); \
-            Py_DECREF(_res); \
-            if (r < 0) \
-                return NULL; \
+            if (self->raw != NULL) \
+                r = _PyFileIO_closed(self->raw); \
+            else { \
+                _res = TextIOWrapper_closed_get(self, NULL); \
+                if (_res == NULL) \
+                    return NULL; \
+                r = PyObject_IsTrue(_res); \
+                Py_DECREF(_res); \
+                if (r < 0) \
+                    return NULL; \
+            } \
             if (r > 0) { \
                 PyErr_SetString(PyExc_ValueError, \
                                 "I/O operation on closed file."); \


More information about the Python-checkins mailing list