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

Commit73f7fb2

Browse files
committed
Set socket options in child process after forking
Try to minimize the work done in the postmaster process for eachaccepted connection, so that postmaster can quickly proceed with itsduties. These function calls are very fast so this doesn't make anymeasurable performance difference in practice, but it's nice to haveall the socket options initialization code in one place for sake ofreadability too. This also paves the way for an upcoming commit thatwill move the initialization of the Port struct to the child process.Discussion:https://www.postgresql.org/message-id/7a59b073-5b5b-151e-7ed3-8b01ff7ce9ef@iki.fi
1 parentf8c5317 commit73f7fb2

File tree

1 file changed

+96
-100
lines changed

1 file changed

+96
-100
lines changed

‎src/backend/libpq/pqcomm.c

Lines changed: 96 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -171,9 +171,102 @@ WaitEventSet *FeBeWaitSet;
171171
void
172172
pq_init(void)
173173
{
174+
Port*port=MyProcPort;
174175
intsocket_posPG_USED_FOR_ASSERTS_ONLY;
175176
intlatch_posPG_USED_FOR_ASSERTS_ONLY;
176177

178+
/* fill in the server (local) address */
179+
port->laddr.salen=sizeof(port->laddr.addr);
180+
if (getsockname(port->sock,
181+
(structsockaddr*)&port->laddr.addr,
182+
&port->laddr.salen)<0)
183+
{
184+
ereport(FATAL,
185+
(errmsg("%s() failed: %m","getsockname")));
186+
}
187+
188+
/* select NODELAY and KEEPALIVE options if it's a TCP connection */
189+
if (port->laddr.addr.ss_family!=AF_UNIX)
190+
{
191+
inton;
192+
#ifdefWIN32
193+
intoldopt;
194+
intoptlen;
195+
intnewopt;
196+
#endif
197+
198+
#ifdefTCP_NODELAY
199+
on=1;
200+
if (setsockopt(port->sock,IPPROTO_TCP,TCP_NODELAY,
201+
(char*)&on,sizeof(on))<0)
202+
{
203+
ereport(FATAL,
204+
(errmsg("%s(%s) failed: %m","setsockopt","TCP_NODELAY")));
205+
}
206+
#endif
207+
on=1;
208+
if (setsockopt(port->sock,SOL_SOCKET,SO_KEEPALIVE,
209+
(char*)&on,sizeof(on))<0)
210+
{
211+
ereport(FATAL,
212+
(errmsg("%s(%s) failed: %m","setsockopt","SO_KEEPALIVE")));
213+
}
214+
215+
#ifdefWIN32
216+
217+
/*
218+
* This is a Win32 socket optimization. The OS send buffer should be
219+
* large enough to send the whole Postgres send buffer in one go, or
220+
* performance suffers. The Postgres send buffer can be enlarged if a
221+
* very large message needs to be sent, but we won't attempt to
222+
* enlarge the OS buffer if that happens, so somewhat arbitrarily
223+
* ensure that the OS buffer is at least PQ_SEND_BUFFER_SIZE * 4.
224+
* (That's 32kB with the current default).
225+
*
226+
* The default OS buffer size used to be 8kB in earlier Windows
227+
* versions, but was raised to 64kB in Windows 2012. So it shouldn't
228+
* be necessary to change it in later versions anymore. Changing it
229+
* unnecessarily can even reduce performance, because setting
230+
* SO_SNDBUF in the application disables the "dynamic send buffering"
231+
* feature that was introduced in Windows 7. So before fiddling with
232+
* SO_SNDBUF, check if the current buffer size is already large enough
233+
* and only increase it if necessary.
234+
*
235+
* See https://support.microsoft.com/kb/823764/EN-US/ and
236+
* https://msdn.microsoft.com/en-us/library/bb736549%28v=vs.85%29.aspx
237+
*/
238+
optlen=sizeof(oldopt);
239+
if (getsockopt(port->sock,SOL_SOCKET,SO_SNDBUF, (char*)&oldopt,
240+
&optlen)<0)
241+
{
242+
ereport(FATAL,
243+
(errmsg("%s(%s) failed: %m","getsockopt","SO_SNDBUF")));
244+
}
245+
newopt=PQ_SEND_BUFFER_SIZE*4;
246+
if (oldopt<newopt)
247+
{
248+
if (setsockopt(port->sock,SOL_SOCKET,SO_SNDBUF, (char*)&newopt,
249+
sizeof(newopt))<0)
250+
{
251+
ereport(FATAL,
252+
(errmsg("%s(%s) failed: %m","setsockopt","SO_SNDBUF")));
253+
}
254+
}
255+
#endif
256+
257+
/*
258+
* Also apply the current keepalive parameters. If we fail to set a
259+
* parameter, don't error out, because these aren't universally
260+
* supported. (Note: you might think we need to reset the GUC
261+
* variables to 0 in such a case, but it's not necessary because the
262+
* show hooks for these variables report the truth anyway.)
263+
*/
264+
(void)pq_setkeepalivesidle(tcp_keepalives_idle,port);
265+
(void)pq_setkeepalivesinterval(tcp_keepalives_interval,port);
266+
(void)pq_setkeepalivescount(tcp_keepalives_count,port);
267+
(void)pq_settcpusertimeout(tcp_user_timeout,port);
268+
}
269+
177270
/* initialize state variables */
178271
PqSendBufferSize=PQ_SEND_BUFFER_SIZE;
179272
PqSendBuffer=MemoryContextAlloc(TopMemoryContext,PqSendBufferSize);
@@ -191,21 +284,21 @@ pq_init(void)
191284
* writes.
192285
*/
193286
#ifndefWIN32
194-
if (!pg_set_noblock(MyProcPort->sock))
287+
if (!pg_set_noblock(port->sock))
195288
ereport(FATAL,
196289
(errmsg("could not set socket to nonblocking mode: %m")));
197290
#endif
198291

199292
#ifndefWIN32
200293

201294
/* Don't give the socket to any subprograms we execute. */
202-
if (fcntl(MyProcPort->sock,F_SETFD,FD_CLOEXEC)<0)
295+
if (fcntl(port->sock,F_SETFD,FD_CLOEXEC)<0)
203296
elog(FATAL,"fcntl(F_SETFD) failed on socket: %m");
204297
#endif
205298

206299
FeBeWaitSet=CreateWaitEventSet(NULL,FeBeWaitSetNEvents);
207300
socket_pos=AddWaitEventToSet(FeBeWaitSet,WL_SOCKET_WRITEABLE,
208-
MyProcPort->sock,NULL,NULL);
301+
port->sock,NULL,NULL);
209302
latch_pos=AddWaitEventToSet(FeBeWaitSet,WL_LATCH_SET,PGINVALID_SOCKET,
210303
MyLatch,NULL);
211304
AddWaitEventToSet(FeBeWaitSet,WL_POSTMASTER_DEATH,PGINVALID_SOCKET,
@@ -713,103 +806,6 @@ StreamConnection(pgsocket server_fd, Port *port)
713806
returnSTATUS_ERROR;
714807
}
715808

716-
/* fill in the server (local) address */
717-
port->laddr.salen=sizeof(port->laddr.addr);
718-
if (getsockname(port->sock,
719-
(structsockaddr*)&port->laddr.addr,
720-
&port->laddr.salen)<0)
721-
{
722-
ereport(LOG,
723-
(errmsg("%s() failed: %m","getsockname")));
724-
returnSTATUS_ERROR;
725-
}
726-
727-
/* select NODELAY and KEEPALIVE options if it's a TCP connection */
728-
if (port->laddr.addr.ss_family!=AF_UNIX)
729-
{
730-
inton;
731-
#ifdefWIN32
732-
intoldopt;
733-
intoptlen;
734-
intnewopt;
735-
#endif
736-
737-
#ifdefTCP_NODELAY
738-
on=1;
739-
if (setsockopt(port->sock,IPPROTO_TCP,TCP_NODELAY,
740-
(char*)&on,sizeof(on))<0)
741-
{
742-
ereport(LOG,
743-
(errmsg("%s(%s) failed: %m","setsockopt","TCP_NODELAY")));
744-
returnSTATUS_ERROR;
745-
}
746-
#endif
747-
on=1;
748-
if (setsockopt(port->sock,SOL_SOCKET,SO_KEEPALIVE,
749-
(char*)&on,sizeof(on))<0)
750-
{
751-
ereport(LOG,
752-
(errmsg("%s(%s) failed: %m","setsockopt","SO_KEEPALIVE")));
753-
returnSTATUS_ERROR;
754-
}
755-
756-
#ifdefWIN32
757-
758-
/*
759-
* This is a Win32 socket optimization. The OS send buffer should be
760-
* large enough to send the whole Postgres send buffer in one go, or
761-
* performance suffers. The Postgres send buffer can be enlarged if a
762-
* very large message needs to be sent, but we won't attempt to
763-
* enlarge the OS buffer if that happens, so somewhat arbitrarily
764-
* ensure that the OS buffer is at least PQ_SEND_BUFFER_SIZE * 4.
765-
* (That's 32kB with the current default).
766-
*
767-
* The default OS buffer size used to be 8kB in earlier Windows
768-
* versions, but was raised to 64kB in Windows 2012. So it shouldn't
769-
* be necessary to change it in later versions anymore. Changing it
770-
* unnecessarily can even reduce performance, because setting
771-
* SO_SNDBUF in the application disables the "dynamic send buffering"
772-
* feature that was introduced in Windows 7. So before fiddling with
773-
* SO_SNDBUF, check if the current buffer size is already large enough
774-
* and only increase it if necessary.
775-
*
776-
* See https://support.microsoft.com/kb/823764/EN-US/ and
777-
* https://msdn.microsoft.com/en-us/library/bb736549%28v=vs.85%29.aspx
778-
*/
779-
optlen=sizeof(oldopt);
780-
if (getsockopt(port->sock,SOL_SOCKET,SO_SNDBUF, (char*)&oldopt,
781-
&optlen)<0)
782-
{
783-
ereport(LOG,
784-
(errmsg("%s(%s) failed: %m","getsockopt","SO_SNDBUF")));
785-
returnSTATUS_ERROR;
786-
}
787-
newopt=PQ_SEND_BUFFER_SIZE*4;
788-
if (oldopt<newopt)
789-
{
790-
if (setsockopt(port->sock,SOL_SOCKET,SO_SNDBUF, (char*)&newopt,
791-
sizeof(newopt))<0)
792-
{
793-
ereport(LOG,
794-
(errmsg("%s(%s) failed: %m","setsockopt","SO_SNDBUF")));
795-
returnSTATUS_ERROR;
796-
}
797-
}
798-
#endif
799-
800-
/*
801-
* Also apply the current keepalive parameters. If we fail to set a
802-
* parameter, don't error out, because these aren't universally
803-
* supported. (Note: you might think we need to reset the GUC
804-
* variables to 0 in such a case, but it's not necessary because the
805-
* show hooks for these variables report the truth anyway.)
806-
*/
807-
(void)pq_setkeepalivesidle(tcp_keepalives_idle,port);
808-
(void)pq_setkeepalivesinterval(tcp_keepalives_interval,port);
809-
(void)pq_setkeepalivescount(tcp_keepalives_count,port);
810-
(void)pq_settcpusertimeout(tcp_user_timeout,port);
811-
}
812-
813809
returnSTATUS_OK;
814810
}
815811

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp