1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-06 07:49:08 +03:00

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
This commit is contained in:
Andres Freund
2017-10-11 16:01:52 -07:00
parent 70c2d1be2b
commit 1de09ad8eb
4 changed files with 208 additions and 70 deletions

View File

@@ -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);
}
}
@@ -227,53 +239,6 @@ pq_send_ascii_string(StringInfo buf, const char *str)
appendStringInfoChar(buf, '\0');
}
/* --------------------------------
* 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
*
@@ -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

View File

@@ -41,17 +41,6 @@
#include "utils/memutils.h"
#include "utils/syscache.h"
/*
* When converting strings between different encodings, we assume that space
* for converted result is 4-to-1 growth in the worst case. The rate for
* currently supported encoding pairs are within 3 (SJIS JIS X0201 half width
* kanna -> UTF8 is the worst case). So "4" should be enough for the moment.
*
* Note that this is not the same as the maximum character width in any
* particular encoding.
*/
#define MAX_CONVERSION_GROWTH 4
/*
* We maintain a simple linked list caching the fmgr lookup info for the
* currently selected conversion functions, as well as any that have been