Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit1de09ad

Browse files
committed
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 FreundDiscussion:https://postgr.es/m/20170914063418.sckdzgjfrsbekae4@alap3.anarazel.de
1 parent70c2d1b commit1de09ad

File tree

4 files changed

+208
-70
lines changed

4 files changed

+208
-70
lines changed

‎src/backend/libpq/pqformat.c

Lines changed: 33 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -97,13 +97,24 @@ pq_beginmessage(StringInfo buf, char msgtype)
9797
}
9898

9999
/* --------------------------------
100-
*pq_sendbyte- append a raw byte to a StringInfo buffer
100+
101+
*pq_beginmessage_reuse - initialize for sending a message, reuse buffer
102+
*
103+
* This requires the buffer to be allocated in an sufficiently long-lived
104+
* memory context.
101105
* --------------------------------
102106
*/
103107
void
104-
pq_sendbyte(StringInfobuf,intbyt)
108+
pq_beginmessage_reuse(StringInfobuf,charmsgtype)
105109
{
106-
appendStringInfoCharMacro(buf,byt);
110+
resetStringInfo(buf);
111+
112+
/*
113+
* We stash the message type into the buffer's cursor field, expecting
114+
* that the pq_sendXXX routines won't touch it. We could alternatively
115+
* make it the first byte of the buffer contents, but this seems easier.
116+
*/
117+
buf->cursor=msgtype;
107118
}
108119

109120
/* --------------------------------
@@ -113,6 +124,7 @@ pq_sendbyte(StringInfo buf, int byt)
113124
void
114125
pq_sendbytes(StringInfobuf,constchar*data,intdatalen)
115126
{
127+
/* use variant that maintains a trailing null-byte, out of caution */
116128
appendBinaryStringInfo(buf,data,datalen);
117129
}
118130

@@ -137,13 +149,13 @@ pq_sendcountedtext(StringInfo buf, const char *str, int slen,
137149
if (p!=str)/* actual conversion has been done? */
138150
{
139151
slen=strlen(p);
140-
pq_sendint(buf,slen+extra,4);
152+
pq_sendint32(buf,slen+extra);
141153
appendBinaryStringInfoNT(buf,p,slen);
142154
pfree(p);
143155
}
144156
else
145157
{
146-
pq_sendint(buf,slen+extra,4);
158+
pq_sendint32(buf,slen+extra);
147159
appendBinaryStringInfoNT(buf,str,slen);
148160
}
149161
}
@@ -227,53 +239,6 @@ pq_send_ascii_string(StringInfo buf, const char *str)
227239
appendStringInfoChar(buf,'\0');
228240
}
229241

230-
/* --------------------------------
231-
*pq_sendint- append a binary integer to a StringInfo buffer
232-
* --------------------------------
233-
*/
234-
void
235-
pq_sendint(StringInfobuf,inti,intb)
236-
{
237-
unsignedcharn8;
238-
uint16n16;
239-
uint32n32;
240-
241-
switch (b)
242-
{
243-
case1:
244-
n8= (unsignedchar)i;
245-
appendBinaryStringInfoNT(buf, (char*)&n8,1);
246-
break;
247-
case2:
248-
n16=pg_hton16((uint16)i);
249-
appendBinaryStringInfoNT(buf, (char*)&n16,2);
250-
break;
251-
case4:
252-
n32=pg_hton32((uint32)i);
253-
appendBinaryStringInfoNT(buf, (char*)&n32,4);
254-
break;
255-
default:
256-
elog(ERROR,"unsupported integer size %d",b);
257-
break;
258-
}
259-
}
260-
261-
/* --------------------------------
262-
*pq_sendint64- append a binary 8-byte int to a StringInfo buffer
263-
*
264-
* It is tempting to merge this with pq_sendint, but we'd have to make the
265-
* argument int64 for all data widths --- that could be a big performance
266-
* hit on machines where int64 isn't efficient.
267-
* --------------------------------
268-
*/
269-
void
270-
pq_sendint64(StringInfobuf,int64i)
271-
{
272-
uint64n64=pg_hton64(i);
273-
274-
appendBinaryStringInfoNT(buf, (char*)&n64,sizeof(n64));
275-
}
276-
277242
/* --------------------------------
278243
*pq_sendfloat4- append a float4 to a StringInfo buffer
279244
*
@@ -295,9 +260,7 @@ pq_sendfloat4(StringInfo buf, float4 f)
295260
}swap;
296261

297262
swap.f=f;
298-
swap.i=pg_hton32(swap.i);
299-
300-
appendBinaryStringInfoNT(buf, (char*)&swap.i,4);
263+
pq_sendint32(buf,swap.i);
301264
}
302265

303266
/* --------------------------------
@@ -341,6 +304,21 @@ pq_endmessage(StringInfo buf)
341304
buf->data=NULL;
342305
}
343306

307+
/* --------------------------------
308+
*pq_endmessage_reuse- send the completed message to the frontend
309+
*
310+
* The data buffer is *not* freed, allowing to reuse the buffer with
311+
* pg_beginmessage_reuse.
312+
--------------------------------
313+
*/
314+
315+
void
316+
pq_endmessage_reuse(StringInfobuf)
317+
{
318+
/* msgtype was saved in cursor field */
319+
(void)pq_putmessage(buf->cursor,buf->data,buf->len);
320+
}
321+
344322

345323
/* --------------------------------
346324
*pq_begintypsend- initialize for constructing a bytea result

‎src/backend/utils/mb/mbutils.c

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -41,17 +41,6 @@
4141
#include"utils/memutils.h"
4242
#include"utils/syscache.h"
4343

44-
/*
45-
* When converting strings between different encodings, we assume that space
46-
* for converted result is 4-to-1 growth in the worst case. The rate for
47-
* currently supported encoding pairs are within 3 (SJIS JIS X0201 half width
48-
* kanna -> UTF8 is the worst case). So "4" should be enough for the moment.
49-
*
50-
* Note that this is not the same as the maximum character width in any
51-
* particular encoding.
52-
*/
53-
#defineMAX_CONVERSION_GROWTH 4
54-
5544
/*
5645
* We maintain a simple linked list caching the fmgr lookup info for the
5746
* currently selected conversion functions, as well as any that have been

‎src/include/libpq/pqformat.h

Lines changed: 164 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,180 @@
1414
#definePQFORMAT_H
1515

1616
#include"lib/stringinfo.h"
17+
#include"mb/pg_wchar.h"
18+
#include"port/pg_bswap.h"
1719

1820
externvoidpq_beginmessage(StringInfobuf,charmsgtype);
19-
externvoidpq_sendbyte(StringInfobuf,intbyt);
21+
externvoidpq_beginmessage_reuse(StringInfobuf,charmsgtype);
22+
externvoidpq_endmessage(StringInfobuf);
23+
externvoidpq_endmessage_reuse(StringInfobuf);
24+
2025
externvoidpq_sendbytes(StringInfobuf,constchar*data,intdatalen);
2126
externvoidpq_sendcountedtext(StringInfobuf,constchar*str,intslen,
2227
boolcountincludesself);
2328
externvoidpq_sendtext(StringInfobuf,constchar*str,intslen);
2429
externvoidpq_sendstring(StringInfobuf,constchar*str);
2530
externvoidpq_send_ascii_string(StringInfobuf,constchar*str);
26-
externvoidpq_sendint(StringInfobuf,inti,intb);
27-
externvoidpq_sendint64(StringInfobuf,int64i);
2831
externvoidpq_sendfloat4(StringInfobuf,float4f);
2932
externvoidpq_sendfloat8(StringInfobuf,float8f);
30-
externvoidpq_endmessage(StringInfobuf);
33+
34+
externvoidpq_sendfloat4(StringInfobuf,float4f);
35+
externvoidpq_sendfloat8(StringInfobuf,float8f);
36+
37+
/*
38+
* Append a int8 to a StringInfo buffer, which already has enough space
39+
* preallocated.
40+
*
41+
* The use of restrict allows the compiler to optimize the code based on the
42+
* assumption that buf, buf->len, buf->data and *buf->data don't
43+
* overlap. Without the annotation buf->len etc cannot be kept in a register
44+
* over subsequent pq_writeint* calls.
45+
*/
46+
staticinlinevoid
47+
pq_writeint8(StringInfo restrictbuf,int8i)
48+
{
49+
int8ni=i;
50+
51+
Assert(buf->len+sizeof(i) <=buf->maxlen);
52+
memcpy((char*restrict) (buf->data+buf->len),&ni,sizeof(ni));
53+
buf->len+=sizeof(i);
54+
}
55+
56+
/*
57+
* Append a int16 to a StringInfo buffer, which already has enough space
58+
* preallocated.
59+
*/
60+
staticinlinevoid
61+
pq_writeint16(StringInfo restrictbuf,int16i)
62+
{
63+
int16ni=pg_hton16(i);
64+
65+
Assert(buf->len+sizeof(ni) <=buf->maxlen);
66+
memcpy((char*restrict) (buf->data+buf->len),&ni,sizeof(i));
67+
buf->len+=sizeof(i);
68+
}
69+
70+
/*
71+
* Append a int32 to a StringInfo buffer, which already has enough space
72+
* preallocated.
73+
*/
74+
staticinlinevoid
75+
pq_writeint32(StringInfo restrictbuf,int32i)
76+
{
77+
int32ni=pg_hton32(i);
78+
79+
Assert(buf->len+sizeof(i) <=buf->maxlen);
80+
memcpy((char*restrict) (buf->data+buf->len),&ni,sizeof(i));
81+
buf->len+=sizeof(i);
82+
}
83+
84+
/*
85+
* Append a int64 to a StringInfo buffer, which already has enough space
86+
* preallocated.
87+
*/
88+
staticinlinevoid
89+
pq_writeint64(StringInfo restrictbuf,int64i)
90+
{
91+
int64ni=pg_hton64(i);
92+
93+
Assert(buf->len+sizeof(i) <=buf->maxlen);
94+
memcpy((char*restrict) (buf->data+buf->len),&ni,sizeof(i));
95+
buf->len+=sizeof(i);
96+
}
97+
98+
/*
99+
* Append a null-terminated text string (with conversion) to a buffer with
100+
* preallocated space.
101+
*
102+
* NB: The pre-allocated space needs to be sufficient for the string after
103+
* converting to client encoding.
104+
*
105+
* NB: passed text string must be null-terminated, and so is the data
106+
* sent to the frontend.
107+
*/
108+
staticinlinevoid
109+
pq_writestring(StringInfo restrictbuf,constchar*restrictstr)
110+
{
111+
intslen=strlen(str);
112+
char*p;
113+
114+
p=pg_server_to_client(str,slen);
115+
if (p!=str)/* actual conversion has been done? */
116+
slen=strlen(p);
117+
118+
Assert(buf->len+slen+1 <=buf->maxlen);
119+
120+
memcpy(((char*restrict)buf->data+buf->len),p,slen+1);
121+
buf->len+=slen+1;
122+
123+
if (p!=str)
124+
pfree(p);
125+
}
126+
127+
/* append a binary int8 to a StringInfo buffer */
128+
staticinlinevoid
129+
pq_sendint8(StringInfobuf,int8i)
130+
{
131+
enlargeStringInfo(buf,sizeof(i));
132+
pq_writeint8(buf,i);
133+
}
134+
135+
/* append a binary int16 to a StringInfo buffer */
136+
staticinlinevoid
137+
pq_sendint16(StringInfobuf,int16i)
138+
{
139+
enlargeStringInfo(buf,sizeof(i));
140+
pq_writeint16(buf,i);
141+
}
142+
143+
/* append a binary int32 to a StringInfo buffer */
144+
staticinlinevoid
145+
pq_sendint32(StringInfobuf,int32i)
146+
{
147+
enlargeStringInfo(buf,sizeof(i));
148+
pq_writeint32(buf,i);
149+
}
150+
151+
/* append a binary int64 to a StringInfo buffer */
152+
staticinlinevoid
153+
pq_sendint64(StringInfobuf,int64i)
154+
{
155+
enlargeStringInfo(buf,sizeof(i));
156+
pq_writeint64(buf,i);
157+
}
158+
159+
/* append a binary byte to a StringInfo buffer */
160+
staticinlinevoid
161+
pq_sendbyte(StringInfobuf,int8byt)
162+
{
163+
pq_sendint8(buf,byt);
164+
}
165+
166+
/*
167+
* Append a binary integer to a StringInfo buffer
168+
*
169+
* This function is deprecated.
170+
*/
171+
staticinlinevoid
172+
pq_sendint(StringInfobuf,inti,intb)
173+
{
174+
switch (b)
175+
{
176+
case1:
177+
pq_sendint8(buf, (int8)i);
178+
break;
179+
case2:
180+
pq_sendint16(buf, (int16)i);
181+
break;
182+
case4:
183+
pq_sendint32(buf, (int32)i);
184+
break;
185+
default:
186+
elog(ERROR,"unsupported integer size %d",b);
187+
break;
188+
}
189+
}
190+
31191

32192
externvoidpq_begintypsend(StringInfobuf);
33193
externbytea*pq_endtypsend(StringInfobuf);

‎src/include/mb/pg_wchar.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,17 @@ typedef enum pg_enc
304304
/* On FE are possible all encodings */
305305
#definePG_VALID_FE_ENCODING(_enc)PG_VALID_ENCODING(_enc)
306306

307+
/*
308+
* When converting strings between different encodings, we assume that space
309+
* for converted result is 4-to-1 growth in the worst case. The rate for
310+
* currently supported encoding pairs are within 3 (SJIS JIS X0201 half width
311+
* kanna -> UTF8 is the worst case). So "4" should be enough for the moment.
312+
*
313+
* Note that this is not the same as the maximum character width in any
314+
* particular encoding.
315+
*/
316+
#defineMAX_CONVERSION_GROWTH 4
317+
307318
/*
308319
* Table for mapping an encoding number to official encoding name and
309320
* possibly other subsidiary data. Be careful to check encoding number

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp