agora inbox for [email protected]
help / color / mirror / Atom feedFrom: Andy Fan <[email protected]>
Subject: [PATCH v20240830 1/1] Avoiding some memcpy, strlen, palloc in printtup.
Date: Fri, 30 Aug 2024 12:50:54 +0800
https://www.postgresql.org/message-id/87wmjzfz0h.fsf%40163.com
---
src/backend/access/common/printtup.c | 40 ++++++++++++++++++++++------
src/backend/utils/adt/oid.c | 20 ++++++++++++++
src/backend/utils/adt/varlena.c | 17 ++++++++++++
src/include/catalog/pg_proc.dat | 9 ++++++-
4 files changed, 77 insertions(+), 9 deletions(-)
diff --git a/src/backend/access/common/printtup.c b/src/backend/access/common/printtup.c
index c78cc39308..ecba4a7113 100644
--- a/src/backend/access/common/printtup.c
+++ b/src/backend/access/common/printtup.c
@@ -19,6 +19,7 @@
#include "libpq/pqformat.h"
#include "libpq/protocol.h"
#include "tcop/pquery.h"
+#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
#include "utils/memdebug.h"
#include "utils/memutils.h"
@@ -49,6 +50,7 @@ typedef struct
bool typisvarlena; /* is it varlena (ie possibly toastable)? */
int16 format; /* format code for this column */
FmgrInfo finfo; /* Precomputed call info for output fn */
+ FmgrInfo p_finfo; /* Precomputed call info for print fn if any */
} PrinttupAttrInfo;
typedef struct
@@ -274,10 +276,25 @@ printtup_prepare_info(DR_printtup *myState, TupleDesc typeinfo, int numAttrs)
thisState->format = format;
if (format == 0)
{
- getTypeOutputInfo(attr->atttypid,
- &thisState->typoutput,
- &thisState->typisvarlena);
- fmgr_info(thisState->typoutput, &thisState->finfo);
+ /*
+ * If the type defines a print function, then use it
+ * rather than outfunction.
+ *
+ * XXX: need a generic function to improve the if-elseif.
+ */
+ if (attr->atttypid == OIDOID)
+ fmgr_info(F_OIDPRINT, &thisState->p_finfo);
+ else if (attr->atttypid == TEXTOID)
+ fmgr_info(F_TEXTPRINT, &thisState->p_finfo);
+ else
+ {
+ getTypeOutputInfo(attr->atttypid,
+ &thisState->typoutput,
+ &thisState->typisvarlena);
+ fmgr_info(thisState->typoutput, &thisState->finfo);
+ /* mark print function is invalid */
+ thisState->p_finfo.fn_oid = InvalidOid;
+ }
}
else if (format == 1)
{
@@ -355,10 +372,17 @@ printtup(TupleTableSlot *slot, DestReceiver *self)
if (thisState->format == 0)
{
/* Text output */
- char *outputstr;
-
- outputstr = OutputFunctionCall(&thisState->finfo, attr);
- pq_sendcountedtext(buf, outputstr, strlen(outputstr));
+ if (thisState->p_finfo.fn_oid)
+ {
+ FunctionCall2(&thisState->p_finfo, attr, PointerGetDatum(buf));
+ }
+ else
+ {
+ char *outputstr;
+
+ outputstr = OutputFunctionCall(&thisState->finfo, attr);
+ pq_sendcountedtext(buf, outputstr, strlen(outputstr));
+ }
}
else
{
diff --git a/src/backend/utils/adt/oid.c b/src/backend/utils/adt/oid.c
index 56fb1fd77c..cc85d920c8 100644
--- a/src/backend/utils/adt/oid.c
+++ b/src/backend/utils/adt/oid.c
@@ -53,6 +53,26 @@ oidout(PG_FUNCTION_ARGS)
PG_RETURN_CSTRING(result);
}
+Datum
+oidprint(PG_FUNCTION_ARGS)
+{
+ Oid o = PG_GETARG_OID(0);
+ StringInfo buf = (StringInfo) PG_GETARG_POINTER(1);
+ uint32 *lenp;
+ uint32 data_len;
+
+ /* 12 is the max length for an oid's text presentation. */
+ enlargeStringInfo(buf, sizeof(int32) + 12);
+
+ /* note the position for len */
+ lenp = (uint32 *) (buf->data + buf->len);
+ data_len = pg_snprintf(buf->data + buf->len + sizeof(int), 12, "%u", o);
+ *lenp = pg_hton32(data_len);
+ buf->len += sizeof(uint32) + data_len;
+
+ PG_RETURN_VOID();
+}
+
/*
* oidrecv - converts external binary format to oid
*/
diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c
index 7c6391a276..3b7006d54a 100644
--- a/src/backend/utils/adt/varlena.c
+++ b/src/backend/utils/adt/varlena.c
@@ -594,6 +594,23 @@ textout(PG_FUNCTION_ARGS)
PG_RETURN_CSTRING(TextDatumGetCString(txt));
}
+
+Datum
+textprint(PG_FUNCTION_ARGS)
+{
+ text *txt = (text *) pg_detoast_datum((struct varlena *)PG_GETARG_POINTER(0));
+ StringInfo buf = (StringInfo) PG_GETARG_POINTER(1);
+ uint32 text_len = VARSIZE(txt) - VARHDRSZ;
+ uint32 ni = pg_hton32(text_len);
+
+ enlargeStringInfo(buf, sizeof(int32) + text_len);
+ memcpy((char *pg_restrict) buf->data + buf->len, &ni, sizeof(uint32));
+ memcpy(buf->data + buf->len + sizeof(int), VARDATA(txt), text_len);
+ buf->len += sizeof(uint32) + text_len;
+
+ PG_RETURN_VOID();
+}
+
/*
* textrecv - converts external binary format to text
*/
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 85f42be1b3..74eeead4de 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -100,6 +100,10 @@
{ oid => '47', descr => 'I/O',
proname => 'textout', prorettype => 'cstring', proargtypes => 'text',
prosrc => 'textout' },
+{
+ oid => '8907', descr => 'I/O',
+ proname => 'textprint', prorettype => 'void', proargtypes => 'text internal',
+ prosrc => 'textprint' },
{ oid => '48', descr => 'I/O',
proname => 'tidin', prorettype => 'tid', proargtypes => 'cstring',
prosrc => 'tidin' },
@@ -4718,7 +4722,10 @@
{ oid => '1799', descr => 'I/O',
proname => 'oidout', prorettype => 'cstring', proargtypes => 'oid',
prosrc => 'oidout' },
-
+{
+ oid => '9771', descr => 'I/O',
+ proname => 'oidprint', prorettype => 'void', proargtypes => 'oid internal',
+ prosrc => 'oidprint'},
{ oid => '3058', descr => 'concatenate values',
proname => 'concat', provariadic => 'any', proisstrict => 'f',
provolatile => 's', prorettype => 'text', proargtypes => 'any',
--
2.45.1
--=-=-=--
view thread (17+ messages)
reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: [email protected]
Cc: [email protected]
Subject: Re: [PATCH v20240830 1/1] Avoiding some memcpy, strlen, palloc in printtup.
In-Reply-To: <no-message-id-77771@localhost>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox