Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT cygwin DOT com Mail-Followup-To: cygwin AT cygwin DOT com Delivered-To: mailing list cygwin AT cygwin DOT com From: Nigel Stephens MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="GdGENvxZW8" Content-Transfer-Encoding: 7bit Message-ID: <16133.60806.834129.78230@highbury.mips.com> Date: Fri, 4 Jul 2003 22:11:34 +0100 To: cygwin AT cygwin DOT com Subject: Patch for slow rsync - select(2) bug X-MTUK-Scanner: Found to be clean X-MTUK-SpamCheck: not spam, SpamAssassin (score=-11.7, required 4, PATCH_UNIFIED_DIFF, USER_AGENT_VM) Note-from-DJ: This may be spam --GdGENvxZW8 Content-Type: text/plain; charset=us-ascii Content-Description: message body and .signature Content-Transfer-Encoding: 7bit After finally getting bored with the poor performance of rsync on Cygwin I decided to investigate. Turns out that when using rsh or ssh as the transport, they soak up 99% of the CPU time. This is because they use non-blocking i/o, but the Cygwin select() function incorrectly returns "ready for read or write", even when there is no buffer space available, so they get stuck in a loop calling select and read/write (which immediately return EWOULDBLOCK). The following patch fixes this problem by correctly initialising the socket's "connect state" for rcmd/rexec sockets and socketpairs, and then maintaining the state correctly across a fork. Note, that this doesn't fix the other problem where rsync often hangs at the end of a transfer. I'll look into this further when I have time. Nigel -- Nigel Stephens Mailto:nigel AT mips DOT com _ _ ____ ___ MIPS Technologies Phone.: +44 1223 706200 |\ /|||___)(___ The Fruit Farm Direct: +44 1223 706207 | \/ ||| ____) Ely Road, Chittering Fax...: +44 1223 706250 TECHNOLOGIES UK Cambridge CB5 9PH Cell..: +44 7976 686470 England http://www.mips.com --GdGENvxZW8 Content-Type: text/plain Content-Disposition: inline; filename="diff" Content-Transfer-Encoding: 7bit Index: cygwin/ChangeLog =================================================================== RCS file: /cvs/src/src/winsup/cygwin/ChangeLog,v retrieving revision 1.1947 diff -u -r1.1947 ChangeLog --- cygwin/ChangeLog 2 Jul 2003 03:50:05 -0000 1.1947 +++ cygwin/ChangeLog 3 Jul 2003 20:59:50 -0000 @@ -1,3 +1,16 @@ +Thu Jul 3 21:54:18 2003 N Stephens + + * net.cc (cygwin_rcmd): Mark file handles of sockets returned by + rcmd() as CONNECTED state. + (cygwin_rexec): Similarly for rexec(). + (socketpair): Mark both ends of a new socket pair as CONNECTED. + + * fhandler_socket.cc (dup): Copy socket connect state to new file + handle. + + * fhandler.h (fhandler_socket::get_connect_state): New method to + return socket connection state. + 2003-07-01 Christopher Faylor * thread.cc: Remove _MT_SAFE conditional. Index: cygwin/fhandler.h =================================================================== RCS file: /cvs/src/src/winsup/cygwin/fhandler.h,v retrieving revision 1.163 diff -u -r1.163 fhandler.h --- cygwin/fhandler.h 26 May 2003 09:54:01 -0000 1.163 +++ cygwin/fhandler.h 3 Jul 2003 20:59:50 -0000 @@ -410,6 +410,7 @@ bool is_connect_pending () const {return had_connect_or_listen == CONNECT_PENDING;} bool is_connected () const {return had_connect_or_listen == CONNECTED;} void set_connect_state (int newstate) { had_connect_or_listen = newstate; } + int get_connect_state () const { return had_connect_or_listen; } int bind (const struct sockaddr *name, int namelen); int connect (const struct sockaddr *name, int namelen); Index: cygwin/fhandler_socket.cc =================================================================== RCS file: /cvs/src/src/winsup/cygwin/fhandler_socket.cc,v retrieving revision 1.106 diff -u -r1.106 fhandler_socket.cc --- cygwin/fhandler_socket.cc 30 Jun 2003 13:07:36 -0000 1.106 +++ cygwin/fhandler_socket.cc 3 Jul 2003 20:59:51 -0000 @@ -320,6 +320,7 @@ if (get_addr_family () == AF_LOCAL) fhs->set_sun_path (get_sun_path ()); fhs->set_socket_type (get_socket_type ()); + fhs->set_connect_state (get_connect_state ()); if (winsock2_active) { Index: cygwin/net.cc =================================================================== RCS file: /cvs/src/src/winsup/cygwin/net.cc,v retrieving revision 1.146 diff -u -r1.146 net.cc --- cygwin/net.cc 19 Jun 2003 00:57:26 -0000 1.146 +++ cygwin/net.cc 3 Jul 2003 20:59:52 -0000 @@ -1997,7 +1997,10 @@ if (res_fd >= 0) fh = fdsock (res_fd, "/dev/tcp", res); if (fh) - res = res_fd; + { + fh->set_connect_state (CONNECTED); + res = res_fd; + } else { closesocket (res); @@ -2011,8 +2014,11 @@ fh = NULL; if (newfd >= 0) fh = fdsock (newfd, "/dev/tcp", fd2s); - if (fh) - *fd2p = newfd; + if (fh) + { + *fd2p = newfd; + fh->set_connect_state (CONNECTED); + } else { closesocket (res); @@ -2081,7 +2087,10 @@ if (res_fd >= 0) fh = fdsock (res_fd, "/dev/tcp", res); if (fh) - res = res_fd; + { + fh->set_connect_state (CONNECTED); + res = res_fd; + } else { closesocket (res); @@ -2096,7 +2105,10 @@ if (newfd >= 0) fh = fdsock (newfd, "/dev/tcp", fd2s); if (fh) - *fd2p = newfd; + { + fh->set_connect_state (CONNECTED); + *fd2p = newfd; + } else { closesocket (res); @@ -2272,6 +2284,7 @@ fh->set_sun_path (""); fh->set_addr_family (family); fh->set_socket_type (type); + fh->set_connect_state (CONNECTED); cygheap_fdnew sb1 (sb0, false); @@ -2283,6 +2296,7 @@ fh->set_sun_path (""); fh->set_addr_family (family); fh->set_socket_type (type); + fh->set_connect_state (CONNECTED); sb[0] = sb0; sb[1] = sb1; --GdGENvxZW8 Content-Type: text/plain; charset=us-ascii -- Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple Problem reports: http://cygwin.com/problems.html Documentation: http://cygwin.com/docs.html FAQ: http://cygwin.com/faq/ --GdGENvxZW8--