List:Commits« Previous MessageNext Message »
From:Davi Arnaut Date:July 2 2010 1:54pm
Subject:bzr commit into mysql-5.1-bugteam branch (davi:3456) Bug#54790
View as plain text  
# At a local mysql-5.1-bugteam repository of davi

 3456 Davi Arnaut	2010-07-02
      Bug#54790: Use of non-blocking mode for sockets limits performance
      
      The problem was that a optimization for the case when the
      server uses alarms for timeouts could cause a slowdown when
      socket timeouts are used instead.
      
      In case alarms are used for timeouts, a non-blocking read
      is attempted first in order to avoid the cost of setting up
      a alarm. If the non-blocking read fails, the socket mode is
      changed to blocking and a alarm is armed.
      
      If socket timeout is used, there is no point in attempting a
      non-blocking read first as the timeout will be automatically
      armed by the OS. Yet the server would attempt a non-blocking
      read first and later switch the socket to blocking mode. This
      could inadvertently impact performance as switching the blocking
      mode of a socket requires at least two calls into the kernel,
      apart from problems inherited by the scalability of fcntl.
      
      The solution is to not attempt a non-blocking read first if
      built-in socket timeouts are being used. Also, in this case,
      spurious interruptions with a errno value of EINTR should
      be ignored.
     @ sql/net_serv.cc
        Do not set socket to non-blocking if not using alarms.
        
        Assert that the socket mode is blocking if using std
        socket timeouts. Also, ignore spurious interruptions
        in this mode.

    modified:
      sql/net_serv.cc
=== modified file 'sql/net_serv.cc'
--- a/sql/net_serv.cc	2010-06-09 08:29:27 +0000
+++ b/sql/net_serv.cc	2010-07-02 13:54:32 +0000
@@ -139,7 +139,7 @@ my_bool my_net_init(NET *net, Vio* vio)
   if (vio != 0)					/* If real connection */
   {
     net->fd  = vio_fd(vio);			/* For perl DBI/DBD */
-#if defined(MYSQL_SERVER) && !defined(__WIN__)
+#if defined(MYSQL_SERVER) && !defined(__WIN__) && !defined(NO_ALARM)
     if (!(test_flags & TEST_BLOCKING))
     {
       my_bool old_mode;
@@ -617,7 +617,7 @@ net_real_write(NET *net,const uchar *pac
     if ((long) (length= vio_write(net->vio,pos,(size_t) (end-pos))) <= 0)
     {
       my_bool interrupted = vio_should_retry(net->vio);
-#if !defined(__WIN__)
+#if !defined(NO_ALARM) && !defined(__WIN__)
       if ((interrupted || length == 0) && !thr_alarm_in_use(&alarmed))
       {
         if (!thr_alarm(&alarmed, net->write_timeout, &alarm_buff))
@@ -655,7 +655,7 @@ net_real_write(NET *net,const uchar *pac
 		  my_progname);
 #endif /* EXTRA_DEBUG */
       }
-#if defined(THREAD_SAFE_CLIENT) && !defined(MYSQL_SERVER)
+#if defined(THREAD_SAFE_CLIENT) && defined(NO_ALARM)
       if (vio_errno(net->vio) == SOCKET_EINTR)
       {
 	DBUG_PRINT("warning",("Interrupted write. Retrying..."));
@@ -673,7 +673,7 @@ net_real_write(NET *net,const uchar *pac
     pos+=length;
     update_statistics(thd_increment_bytes_sent(length));
   }
-#ifndef __WIN__
+#if !defined(NO_ALARM) && !defined(__WIN__)
  end:
 #endif
 #ifdef HAVE_COMPRESS
@@ -805,6 +805,7 @@ my_real_read(NET *net, size_t *complen)
     thr_alarm(&alarmed,net->read_timeout,&alarm_buff);
 #else
   /* Read timeout is set in my_net_set_read_timeout */
+  DBUG_ASSERT(net_blocking);
 #endif /* NO_ALARM */
 
     pos = net->buff + net->where_b;		/* net->packet -4 */
@@ -819,7 +820,8 @@ my_real_read(NET *net, size_t *complen)
 
 	  DBUG_PRINT("info",("vio_read returned %ld  errno: %d",
 			     (long) length, vio_errno(net->vio)));
-#if !defined(__WIN__) || defined(MYSQL_SERVER)
+
+#if !defined(NO_ALARM) && (!defined(__WIN__) || defined(MYSQL_SERVER))
 	  /*
 	    We got an error that there was no data on the socket. We now set up
 	    an alarm to not 'read forever', change the socket to non blocking
@@ -866,7 +868,7 @@ my_real_read(NET *net, size_t *complen)
 		    my_progname,vio_errno(net->vio));
 #endif /* EXTRA_DEBUG */
 	  }
-#if defined(THREAD_SAFE_CLIENT) && !defined(MYSQL_SERVER)
+#if defined(THREAD_SAFE_CLIENT) && defined(NO_ALARM)
 	  if (vio_errno(net->vio) == SOCKET_EINTR)
 	  {
 	    DBUG_PRINT("warning",("Interrupted read. Retrying..."));


Attachment: [text/bzr-bundle] bzr/davi.arnaut@sun.com-20100702135432-4yc89h4gpu7hfhr3.bundle
Thread
bzr commit into mysql-5.1-bugteam branch (davi:3456) Bug#54790Davi Arnaut2 Jul