Read buffer size in clientloop.c

Darren Tucker dtucker at zip.com.au
Tue Jul 7 21:53:37 EST 2009


On Tue, Jul 07, 2009 at 12:57:16PM +0200, Corinna Vinschen wrote:
> when trying to optimize socket transfer rates under Cygwin, it turned
> out that the underlying WinSock implementation is surprisingly sensitive
> to buffer sizes.  The latest Cygwin from CVS is now setting the socket
> receive/send buffers (SO_RCVBUF/SO_SNDBUF) to 64K, rather than keeping
> them at their default values of 8K which thwarts data transfers a lot.
> 
> While testing I still had the problem that for some reason the ssh read
> transfer rates were only a third up to a half of the write transfer
> rates.  It turned out that the culprit was ssh itself.  In clientloop.c,
> it defines read buffers of the size 8K.  Setting them to 64K under
> Cygwin raises the read transfer rates comparable to the write rates.
> 
> It occured to me that we talked about this already 3 years ago in a
> thread about HPN-SSH, just the performance numbers were different:
> http://marc.info/?l=openssh-unix-dev&m=114414372902485&w=2
> 
> So the question I have is again this:
> 
> Would it be ok to raise the buffers in client_process_net_input() and
> client_process_input() to 64K, maybe only on Cygwin?  Or to make the
> buffer sizes a configurable option?

If there's a measureable performance gain (which it sounds like there is)
then I personally have no objection to making it a compile time option.
Damien?  Maybe something like this?

Index: clientloop.c
===================================================================
RCS file: /home/dtucker/openssh/cvs/openssh/clientloop.c,v
retrieving revision 1.201
diff -u -p -r1.201 clientloop.c
--- clientloop.c	5 Jul 2009 21:17:35 -0000	1.201
+++ clientloop.c	7 Jul 2009 11:38:33 -0000
@@ -636,7 +636,7 @@ static void
 client_process_net_input(fd_set *readset)
 {
 	int len, cont = 0;
-	char buf[8192];
+	char buf[SSH_IOBUFSZ];
 
 	/*
 	 * Read input from the server, and add any such data to the buffer of
@@ -1129,7 +1129,7 @@ static void
 client_process_input(fd_set *readset)
 {
 	int len;
-	char buf[8192];
+	char buf[SSH_IOBUFSZ];
 
 	/* Read input from stdin. */
 	if (FD_ISSET(fileno(stdin), readset)) {
Index: configure.ac
===================================================================
RCS file: /home/dtucker/openssh/cvs/openssh/configure.ac,v
retrieving revision 1.420
diff -u -p -r1.420 configure.ac
--- configure.ac	16 Jun 2009 06:11:02 -0000	1.420
+++ configure.ac	7 Jul 2009 11:41:04 -0000
@@ -442,6 +442,7 @@ int main(void) { exit(0); }
 	AC_DEFINE(DISABLE_FD_PASSING, 1,
 		[Define if your platform needs to skip post auth
 		file descriptor passing])
+	AC_DEFINE(SSH_IOBUFSZ, 65536, [Windows is sensitive to read buffer size])
 	;;
 *-*-dgux*)
 	AC_DEFINE(IP_TOS_IS_BROKEN, 1,
Index: defines.h
===================================================================
RCS file: /home/dtucker/openssh/cvs/openssh/defines.h,v
retrieving revision 1.155
diff -u -p -r1.155 defines.h
--- defines.h	16 Jun 2009 06:11:02 -0000	1.155
+++ defines.h	7 Jul 2009 11:39:15 -0000
@@ -749,4 +749,8 @@ struct winsize {
 #define INET6_ADDRSTRLEN 46
 #endif
 
+#ifndef SSH_IOBUFSZ
+# define SSH_IOBUFSZ 8192
+#endif
+
 #endif /* _DEFINES_H */

-- 
Darren Tucker (dtucker at zip.com.au)
GPG key 8FF4FA69 / D9A3 86E9 7EEE AF4B B2D4  37C9 C982 80C7 8FF4 FA69
    Good judgement comes with experience. Unfortunately, the experience
usually comes from bad judgement.


More information about the openssh-unix-dev mailing list