[Python-checkins] r68088 - in sandbox/trunk/io-c: _bufferedio.c _iomodule.h io.c
antoine.pitrou
python-checkins at python.org
Wed Dec 31 03:35:06 CET 2008
Author: antoine.pitrou
Date: Wed Dec 31 03:35:05 2008
New Revision: 68088
Log:
mildly faster BufferedReader seeks, by caching the current raw position
Modified:
sandbox/trunk/io-c/_bufferedio.c
sandbox/trunk/io-c/_iomodule.h
sandbox/trunk/io-c/io.c
Modified: sandbox/trunk/io-c/_bufferedio.c
==============================================================================
--- sandbox/trunk/io-c/_bufferedio.c (original)
+++ sandbox/trunk/io-c/_bufferedio.c Wed Dec 31 03:35:05 2008
@@ -3,6 +3,8 @@
#include "pythread.h"
#include "_iomodule.h"
+/* TODO: offsets must be off_t, not Py_ssize_t. See _fileio.c for examples */
+
/*
* BufferedIOBase class, inherits from IOBase.
*/
@@ -109,6 +111,9 @@
PyObject *raw;
int ok; /* Initialized? */
+ /* Position inside the raw stream (-1 if unknown). */
+ Py_ssize_t raw_pos;
+
/* A static buffer of size `buffer_size` */
unsigned char *read_buf;
/* Current reading pos in the buffer. */
@@ -340,39 +345,20 @@
BufferedIOMixin_fileno(BufferedObject *self, PyObject *args)
{
CHECK_INITIALIZED(self)
- return PyObject_CallMethod(self->raw, "fileno", NULL);
+ return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_fileno, NULL);
}
static PyObject *
BufferedIOMixin_isatty(BufferedObject *self, PyObject *args)
{
CHECK_INITIALIZED(self)
- return PyObject_CallMethod(self->raw, "isatty", NULL);
+ return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_isatty, NULL);
}
/*
* Helpers
*/
-static int
-_Buffered_init(BufferedObject *self)
-{
- Py_ssize_t n;
- if (self->buffer_size <= 0) {
- PyErr_SetString(PyExc_ValueError,
- "buffer size must be strictly positive");
- return -1;
- }
- /* Find out whether buffer_size is a power of 2 */
- for (n = self->buffer_size - 1; n & 1; n >>= 1)
- ;
- if (n == 0)
- self->buffer_mask = self->buffer_size - 1;
- else
- self->buffer_mask = 0;
- return 0;
-}
-
/* Returns the address of the `written` member if a BlockingIOError was
raised, NULL otherwise. The error is always re-raised. */
static Py_ssize_t *
@@ -402,10 +388,47 @@
return -1;
n = PyNumber_AsSsize_t(res, PyExc_ValueError);
Py_DECREF(res);
+ self->raw_pos = n;
/* TODO: sanity check (n >= 0) */
return n;
}
+static Py_ssize_t
+_Buffered_raw_seek(BufferedObject *self, Py_ssize_t target, int whence)
+{
+ PyObject *res;
+ Py_ssize_t n;
+ res = PyObject_CallMethod(self->raw, "seek", "ni", target, whence);
+ if (res == NULL)
+ return -1;
+ n = PyNumber_AsSsize_t(res, PyExc_ValueError);
+ Py_DECREF(res);
+ self->raw_pos = n;
+ /* TODO: sanity check (n >= 0) */
+ return n;
+}
+
+static int
+_Buffered_init(BufferedObject *self)
+{
+ Py_ssize_t n;
+ if (self->buffer_size <= 0) {
+ PyErr_SetString(PyExc_ValueError,
+ "buffer size must be strictly positive");
+ return -1;
+ }
+ /* Find out whether buffer_size is a power of 2 */
+ for (n = self->buffer_size - 1; n & 1; n >>= 1)
+ ;
+ if (n == 0)
+ self->buffer_mask = self->buffer_size - 1;
+ else
+ self->buffer_mask = 0;
+ if (_Buffered_raw_tell(self) == -1)
+ PyErr_Clear();
+ return 0;
+}
+
/*
* class BufferedReader
@@ -491,15 +514,18 @@
n = PyNumber_AsSsize_t(res, PyExc_ValueError);
Py_DECREF(res);
/* TODO: sanity check (0 <= n <= len) */
+ if (n > 0 && self->raw_pos != -1)
+ self->raw_pos += n;
return n;
}
static PyObject *
_BufferedReader_read_unlocked(BufferedObject *self, Py_ssize_t n)
{
- PyObject *data, *chunks, *sep, *res = NULL;
+ PyObject *data, *chunks, *res = NULL;
Py_ssize_t current_size, remaining, written;
unsigned char *out;
+ static PyObject *sep = NULL;
/* Special case for when the number of bytes to read is unspecified. */
if (n == -1) {
@@ -550,19 +576,22 @@
return data;
}
else {
- Py_DECREF(data);
- sep = PyBytes_FromStringAndSize(NULL, 0);
if (sep == NULL) {
- Py_DECREF(chunks);
- return NULL;
+ sep = PyBytes_FromStringAndSize(NULL, 0);
+ if (sep == NULL) {
+ Py_DECREF(data);
+ Py_DECREF(chunks);
+ return NULL;
+ }
}
res =_PyBytes_Join(sep, chunks);
- Py_DECREF(sep);
Py_DECREF(chunks);
return res;
}
}
current_size += PyBytes_GET_SIZE(data);
+ if (self->raw_pos != -1)
+ self->raw_pos += PyBytes_GET_SIZE(data);
}
}
@@ -778,7 +807,7 @@
static PyObject *
BufferedReader_seek(BufferedObject *self, PyObject *args)
{
- Py_ssize_t current, target, avail;
+ Py_ssize_t current, target, avail, n;
int whence = 0;
PyObject *res = NULL;
@@ -790,24 +819,27 @@
ENTER_BUFFERED_READER(self)
- /* TODO: cache the value somewhere rather than always query it*/
- current = _Buffered_raw_tell(self);
- if (current == -1)
- goto end;
- avail = AVAILABLE_BYTES(self);
- if (avail > 0 && whence != 2) {
+ if (whence != 2) {
/* Check if seeking leaves us inside the current buffer,
so as to return quickly if possible.
Don't know how to do that when whence == 2, though. */
- Py_ssize_t offset;
- if (whence == 0)
- offset = target - (current - avail);
- else
- offset = target;
- if (offset >= -self->read_pos && offset <= avail) {
- self->read_pos += offset;
- res = PyLong_FromSsize_t(current - avail + offset);
+ current = self->raw_pos;
+ if (current == -1)
+ current = _Buffered_raw_tell(self);
+ if (current == -1)
goto end;
+ avail = AVAILABLE_BYTES(self);
+ if (avail > 0) {
+ Py_ssize_t offset;
+ if (whence == 0)
+ offset = target - (current - avail);
+ else
+ offset = target;
+ if (offset >= -self->read_pos && offset <= avail) {
+ self->read_pos += offset;
+ res = PyLong_FromSsize_t(current - avail + offset);
+ goto end;
+ }
}
}
@@ -816,10 +848,11 @@
target -= AVAILABLE_BYTES(self);
/* TODO: align on block boundary and read buffer if needed? */
- res = PyObject_CallMethod(self->raw, "seek", "ni", target, whence);
- if (res == NULL)
+ n = _Buffered_raw_seek(self, target, whence);
+ if (n == -1)
goto end;
- if (_BufferedReader_reset_buf(self) < 0)
+ res = PyLong_FromSsize_t(n);
+ if (res != NULL && _BufferedReader_reset_buf(self) < 0)
Py_CLEAR(res);
end:
@@ -1641,16 +1674,20 @@
* if the raw seek fails, we don't lose buffered data forever.
*/
- res = PyObject_CallMethod(self->raw, "seek", "ni", pos, whence);
- if (res == NULL)
- return NULL;
-
ENTER_BUFFERED_READER(self)
+ pos = _Buffered_raw_seek(self, pos, whence);
+ if (pos == -1)
+ goto end;
+ res = PyLong_FromSsize_t(pos);
+ if (res == NULL)
+ goto end;
+
if (_BufferedReader_reset_buf(self) < 0
|| _BufferedWriter_reset_buf(self) < 0)
Py_CLEAR(res);
+end:
LEAVE_BUFFERED_READER(self)
return res;
}
Modified: sandbox/trunk/io-c/_iomodule.h
==============================================================================
--- sandbox/trunk/io-c/_iomodule.h (original)
+++ sandbox/trunk/io-c/_iomodule.h Wed Dec 31 03:35:05 2008
@@ -51,7 +51,9 @@
/* Implementation details */
extern PyObject *_PyIO_str_closed;
+extern PyObject *_PyIO_str_fileno;
extern PyObject *_PyIO_str_flush;
+extern PyObject *_PyIO_str_isatty;
extern PyObject *_PyIO_str_read;
extern PyObject *_PyIO_str_readable;
extern PyObject *_PyIO_str_readinto;
Modified: sandbox/trunk/io-c/io.c
==============================================================================
--- sandbox/trunk/io-c/io.c (original)
+++ sandbox/trunk/io-c/io.c Wed Dec 31 03:35:05 2008
@@ -2,12 +2,22 @@
#include "structmember.h"
#include "_iomodule.h"
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif /* HAVE_SYS_TYPES_H */
+
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif /* HAVE_SYS_STAT_H */
+
PyObject *PyIOExc_UnsupportedOperation;
/* Various interned strings */
PyObject *_PyIO_str_closed;
+PyObject *_PyIO_str_fileno;
PyObject *_PyIO_str_flush;
+PyObject *_PyIO_str_isatty;
PyObject *_PyIO_str_read;
PyObject *_PyIO_str_readable;
PyObject *_PyIO_str_readinto;
@@ -614,8 +624,12 @@
/* Interned strings */
if (!(_PyIO_str_closed = PyUnicode_InternFromString("closed")))
goto fail;
+ if (!(_PyIO_str_fileno = PyUnicode_InternFromString("fileno")))
+ goto fail;
if (!(_PyIO_str_flush = PyUnicode_InternFromString("flush")))
goto fail;
+ if (!(_PyIO_str_isatty = PyUnicode_InternFromString("isatty")))
+ goto fail;
if (!(_PyIO_str_read = PyUnicode_InternFromString("read")))
goto fail;
if (!(_PyIO_str_readable = PyUnicode_InternFromString("readable")))
More information about the Python-checkins
mailing list