On 04/10/2015 01:46 PM, chenhj wrote:
PostgreSQL set Win32 server-side socket buffer size to 32k since 2006, for
performance reasons.
While,on the newer version of Windows,such as windows 2012,the default socket
buffer size is 64k,
and seem has better performance(high throughput).
So, i propose to apply the attached patch(based on the snapshot of 9.5dev) to
set Win32 server-side
socket buffer size to 32k only when the default value is less than 32k.
Seems reasonable. I edited the comment somewhat, and added #ifdefs on
the new variables to avoid compiler warnings on other platforms.
OSdefault socket buffer size(get from getsockopt(SO_SNDBUF))
Window7: 8k
Windows2003:8k
Windows2008:8k
Windows8: 64k
Windows2012:64k
The following is my performance test for various SO_SNDBUF setting.
Test method:
Use psql to fetch about 100MB data from PostgreSQL(Windows) with various
SO_SNDBUF setting.
[chenhj@node2 ~]$ time psql -h dbsvr -p 5432 -U postgres -A -t -c "select
'1'::char(10000000),generate_series(1,10)">/dev/null
real0m3.295s
user0m0.222s
sys0m0.250s
Environment1(default SO_SNDBUF >32k):
Client: PostgreSQL 9.4.1 at RHEL6(x64)
Server: PostgreSQL 9.4.1 at Windows 2012(x64)
Network:1Gbit LAN
Result(execute time):
default(64K), 1.118s
set SO_SNDBUF to 32K, 3.295s(the current implement)
set SO_SNDBUF to 64K, 2.048s
set SO_SNDBUF to 128K, 1.404s
set SO_SNDBUF to 256K, 1.290s
1)When use Windows as client OS,the result is similar,but there's no
"/dev/null" used by my test in windows.
2)I think the reason that the default(64K) is fast than "set SO_SNDBUF to 64K"
is
that dynamic send buffering was disabled after set SO_SNDBUF option.
https://msdn.microsoft.com/en-us/library/windows/desktop/bb736549(v=vs.85).aspx
------------------------------------------------------------
Dynamic send buffering for TCP was added on Windows 7 and Windows Server 2008
R2. By default,
dynamic send buffering for TCP is enabled unless an application sets the
SO_SNDBUF socket option on the stream socket.
------------------------------------------------------------
Environment2(default SO_SNDBUF <32k):
Client: PostgreSQL 9.4.1 at RHEL6(x64)
Server: PostgreSQL 9.4.1 at Windows 2008 R2(x64)
Network:1Gbit LAN
Result(execute time):
default(8K), 7.370s
set SO_SNDBUF to 32K, 4.159s(the current implement)
set SO_SNDBUF to 64K, 2.875s
set SO_SNDBUF to 128K, 1.593s
set SO_SNDBUF to 256K, 1.324s
I was about to commit the attached, but when I tested this between my
Windows 8.1 virtual machine and Linux host, I was not able to see any
performance difference. It may be because the case is hobbled by other
inefficiencies, in the virtualization or somewhere else, but I wonder if
others can reproduce the speedup?
- Heikki
>From 2a8b9c5fe10d5b8dc4e4bcf00ed0025bc6d24a23 Mon Sep 17 00:00:00 2001
From: Heikki Linnakangas <heikki.linnakan...@iki.fi>
Date: Thu, 2 Jul 2015 22:09:08 +0300
Subject: [PATCH 1/1] Don't set SO_SNDBUF on recent Windows versions that have
a bigger default.
It's unnecessary to set it if the default is higher in the first place.
Furthermore, setting SO_SNDBUF disables the so-called "dynamic send
buffering" feature, which hurts performance further.
Chen Huajun
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index a4b37ed..7672287 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -726,6 +726,11 @@ StreamConnection(pgsocket server_fd, Port *port)
if (!IS_AF_UNIX(port->laddr.addr.ss_family))
{
int on;
+#ifdef WIN32
+ int oldopt;
+ int optlen;
+ int newopt;
+#endif
#ifdef TCP_NODELAY
on = 1;
@@ -747,16 +752,43 @@ StreamConnection(pgsocket server_fd, Port *port)
#ifdef WIN32
/*
- * This is a Win32 socket optimization. The ideal size is 32k.
- * http://support.microsoft.com/kb/823764/EN-US/
+ * This is a Win32 socket optimization. The OS send buffer should be
+ * large enough to send the whole Postgres send buffer in one go, or
+ * performance suffers. The Postgres send buffer can be enlarged if a
+ * very large message needs to be sent, but we won't attempt to
+ * enlarge the OS buffer if that happens, so somewhat arbitrarily
+ * ensure that the OS buffer is at least PQ_SEND_BUFFER_SIZE * 4.
+ * (That's 32kB with the current default).
+ *
+ * The default OS buffer size used to be 8kB in earlier Windows
+ * versions, but was raised to 64kB in Windows 2012. So it shouldn't
+ * be necessary to change it in later versions anymore. Changing it
+ * unnecessarily can even reduce performance, because setting
+ * SO_SNDBUF in the application disables the "dynamic send buffering"
+ * feature that was introduced in Windows 7. So before fiddling with
+ * SO_SNDBUF, check if the current buffers size is already large
+ * enough and only increase it if necessary.
+ *
+ * See https://support.microsoft.com/kb/823764/EN-US/ and
+ * https://msdn.microsoft.com/en-us/library/bb736549%28v=vs.85%29.aspx
*/
- on = PQ_SEND_BUFFER_SIZE * 4;
- if (setsockopt(port->sock, SOL_SOCKET, SO_SNDBUF, (char *) &on,
- sizeof(on)) < 0)
+ optlen = sizeof(oldopt);
+ if (getsockopt(server_fd, SOL_SOCKET, SO_SNDBUF, (char *) &oldopt,
+ &optlen) < 0)
{
- elog(LOG, "setsockopt(SO_SNDBUF) failed: %m");
+ elog(LOG, "getsockopt(SO_SNDBUF) failed: %m");
return STATUS_ERROR;
}
+ newopt = PQ_SEND_BUFFER_SIZE * 4;
+ if (oldopt < newopt)
+ {
+ if (setsockopt(port->sock, SOL_SOCKET, SO_SNDBUF, (char *) &newopt,
+ sizeof(newopt)) < 0)
+ {
+ elog(LOG, "setsockopt(SO_SNDBUF) failed: %m");
+ return STATUS_ERROR;
+ }
+ }
#endif
/*
--
2.1.4
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers