Optimize UTF8 and Latin1 decoding

Cache a pointer to a fast decoding function when the connection encoding
is set so skip a repeated codec lookup for every string.
This commit is contained in:
Daniele Varrazzo 2016-10-12 01:10:31 +01:00
parent 584c7e6890
commit 121cf3b8f8
3 changed files with 40 additions and 3 deletions

View File

@ -122,6 +122,9 @@ struct connectionObject {
int autocommit;
PyObject *cursor_factory; /* default cursor factory from cursor() */
/* Pointer to a decoding function, e.g. PyUnicode_DecodeUTF8 */
PyObject *(*cdecoder)(const char *, Py_ssize_t, const char *);
};
/* map isolation level values into a numeric const */

View File

@ -361,6 +361,31 @@ exit:
return rv;
}
/* set fast access functions according to the currently selected codec
*/
void
conn_set_fast_codec(connectionObject *self)
{
Dprintf("conn_set_fast_codec: codec=%s", self->codec);
if (0 == strcmp(self->codec, "utf_8")) {
Dprintf("conn_set_fast_codec: PyUnicode_DecodeUTF8");
self->cdecoder = PyUnicode_DecodeUTF8;
return;
}
if (0 == strcmp(self->codec, "iso8859_1")) {
Dprintf("conn_set_fast_codec: PyUnicode_DecodeLatin1");
self->cdecoder = PyUnicode_DecodeLatin1;
return;
}
Dprintf("conn_set_fast_codec: no fast codec");
self->cdecoder = NULL;
}
/* Read the client encoding from the connection.
*
* Store the encoding in the pgconn->encoding field and the name of the
@ -402,6 +427,8 @@ conn_read_encoding(connectionObject *self, PGconn *pgconn)
self->codec = codec;
codec = NULL;
conn_set_fast_codec(self);
rv = 0;
exit:
@ -1243,6 +1270,8 @@ conn_set_client_encoding(connectionObject *self, const char *enc)
codec = NULL;
}
conn_set_fast_codec(self);
Dprintf("conn_set_client_encoding: set encoding to %s (codec: %s)",
self->encoding, self->codec);

View File

@ -93,12 +93,17 @@ typecast_STRING_cast(const char *s, Py_ssize_t len, PyObject *curs)
static PyObject *
typecast_UNICODE_cast(const char *s, Py_ssize_t len, PyObject *curs)
{
char *enc;
connectionObject *conn;
if (s == NULL) { Py_RETURN_NONE; }
enc = ((cursorObject*)curs)->conn->codec;
return PyUnicode_Decode(s, len, enc, NULL);
conn = ((cursorObject*)curs)->conn;
if (conn->cdecoder) {
return conn->cdecoder(s, len, NULL);
}
else {
return PyUnicode_Decode(s, len, conn->codec, NULL);
}
}
/** BOOLEAN - cast boolean value into right python object **/