diff options
author | Andres Freund <andres@anarazel.de> | 2017-10-11 16:01:52 -0700 |
---|---|---|
committer | Andres Freund <andres@anarazel.de> | 2017-10-11 16:01:52 -0700 |
commit | 1de09ad8eb1fa673ee7899d6dfbb2b49ba204818 (patch) | |
tree | 9e4446d18d50f944a812d6fba7d1c2a085e5ce84 /src/backend/libpq/pqformat.c | |
parent | 70c2d1be2b1e1efa8ef38a92b443fa290a9558dd (diff) | |
download | postgresql-1de09ad8eb1fa673ee7899d6dfbb2b49ba204818.tar.gz postgresql-1de09ad8eb1fa673ee7899d6dfbb2b49ba204818.zip |
Add more efficient functions to pqformat API.
There's three prongs to achieve greater efficiency here:
1) Allow reusing a stringbuffer across pq_beginmessage/endmessage,
with the new pq_beginmessage_reuse/endmessage_reuse. This can be
beneficial both because it avoids allocating the initial buffer,
and because it's more likely to already have an correctly sized
buffer.
2) Replacing pq_sendint() with pq_sendint$width() inline
functions. Previously unnecessary and unpredictable branches in
pq_sendint() were needed. Additionally the replacement functions
are implemented more efficiently. pq_sendint is now deprecated, a
separate commit will convert all in-tree callers.
3) Add pq_writeint$width(), pq_writestring(). These rely on sufficient
space in the StringInfo's buffer, avoiding individual space checks
& potential individual resizing. To allow this to be used for
strings, expose mbutil.c's MAX_CONVERSION_GROWTH.
Followup commits will make use of these facilities.
Author: Andres Freund
Discussion: https://postgr.es/m/20170914063418.sckdzgjfrsbekae4@alap3.anarazel.de
Diffstat (limited to 'src/backend/libpq/pqformat.c')
-rw-r--r-- | src/backend/libpq/pqformat.c | 88 |
1 files changed, 33 insertions, 55 deletions
diff --git a/src/backend/libpq/pqformat.c b/src/backend/libpq/pqformat.c index 2414d0d8e9a..a5698390ae7 100644 --- a/src/backend/libpq/pqformat.c +++ b/src/backend/libpq/pqformat.c @@ -97,13 +97,24 @@ pq_beginmessage(StringInfo buf, char msgtype) } /* -------------------------------- - * pq_sendbyte - append a raw byte to a StringInfo buffer + + * pq_beginmessage_reuse - initialize for sending a message, reuse buffer + * + * This requires the buffer to be allocated in an sufficiently long-lived + * memory context. * -------------------------------- */ void -pq_sendbyte(StringInfo buf, int byt) +pq_beginmessage_reuse(StringInfo buf, char msgtype) { - appendStringInfoCharMacro(buf, byt); + resetStringInfo(buf); + + /* + * We stash the message type into the buffer's cursor field, expecting + * that the pq_sendXXX routines won't touch it. We could alternatively + * make it the first byte of the buffer contents, but this seems easier. + */ + buf->cursor = msgtype; } /* -------------------------------- @@ -113,6 +124,7 @@ pq_sendbyte(StringInfo buf, int byt) void pq_sendbytes(StringInfo buf, const char *data, int datalen) { + /* use variant that maintains a trailing null-byte, out of caution */ appendBinaryStringInfo(buf, data, datalen); } @@ -137,13 +149,13 @@ pq_sendcountedtext(StringInfo buf, const char *str, int slen, if (p != str) /* actual conversion has been done? */ { slen = strlen(p); - pq_sendint(buf, slen + extra, 4); + pq_sendint32(buf, slen + extra); appendBinaryStringInfoNT(buf, p, slen); pfree(p); } else { - pq_sendint(buf, slen + extra, 4); + pq_sendint32(buf, slen + extra); appendBinaryStringInfoNT(buf, str, slen); } } @@ -228,53 +240,6 @@ pq_send_ascii_string(StringInfo buf, const char *str) } /* -------------------------------- - * pq_sendint - append a binary integer to a StringInfo buffer - * -------------------------------- - */ -void -pq_sendint(StringInfo buf, int i, int b) -{ - unsigned char n8; - uint16 n16; - uint32 n32; - - switch (b) - { - case 1: - n8 = (unsigned char) i; - appendBinaryStringInfoNT(buf, (char *) &n8, 1); - break; - case 2: - n16 = pg_hton16((uint16) i); - appendBinaryStringInfoNT(buf, (char *) &n16, 2); - break; - case 4: - n32 = pg_hton32((uint32) i); - appendBinaryStringInfoNT(buf, (char *) &n32, 4); - break; - default: - elog(ERROR, "unsupported integer size %d", b); - break; - } -} - -/* -------------------------------- - * pq_sendint64 - append a binary 8-byte int to a StringInfo buffer - * - * It is tempting to merge this with pq_sendint, but we'd have to make the - * argument int64 for all data widths --- that could be a big performance - * hit on machines where int64 isn't efficient. - * -------------------------------- - */ -void -pq_sendint64(StringInfo buf, int64 i) -{ - uint64 n64 = pg_hton64(i); - - appendBinaryStringInfoNT(buf, (char *) &n64, sizeof(n64)); -} - -/* -------------------------------- * pq_sendfloat4 - append a float4 to a StringInfo buffer * * The point of this routine is to localize knowledge of the external binary @@ -295,9 +260,7 @@ pq_sendfloat4(StringInfo buf, float4 f) } swap; swap.f = f; - swap.i = pg_hton32(swap.i); - - appendBinaryStringInfoNT(buf, (char *) &swap.i, 4); + pq_sendint32(buf, swap.i); } /* -------------------------------- @@ -341,6 +304,21 @@ pq_endmessage(StringInfo buf) buf->data = NULL; } +/* -------------------------------- + * pq_endmessage_reuse - send the completed message to the frontend + * + * The data buffer is *not* freed, allowing to reuse the buffer with + * pg_beginmessage_reuse. + -------------------------------- + */ + +void +pq_endmessage_reuse(StringInfo buf) +{ + /* msgtype was saved in cursor field */ + (void) pq_putmessage(buf->cursor, buf->data, buf->len); +} + /* -------------------------------- * pq_begintypsend - initialize for constructing a bytea result |