]> Sergey Matveev's repositories - btrtrc.git/commitdiff
connection.writer wasn't working efficiently
authorMatt Joiner <anacrolix@gmail.com>
Sun, 2 Aug 2015 10:39:31 +0000 (20:39 +1000)
committerMatt Joiner <anacrolix@gmail.com>
Sun, 2 Aug 2015 10:39:31 +0000 (20:39 +1000)
Because of the pseudo-random selection of a communication in a select statement, flushing was occuring prematurely. Also the buffer was needlessly large. For large messages, like outgoing pieces, it's probably better they just go straight to the wire anyway.

This change will make it easier to implement sending of pieces that doesn't block control messages in the future. Any time that the buffer is empty, we'll be able to signal that it's an optimal time to send a piece.

connection.go

index 1d70c7a7998de34e146d455adb86cea60ac08b55..ba0d124a8f85077dc1b1b1262c94450c6c49a735 100644 (file)
@@ -431,41 +431,57 @@ func (c *connection) SetInterested(interested bool) {
        c.Interested = interested
 }
 
-var connectionWriterFlush = expvar.NewInt("connectionWriterFlush")
-var connectionWriterWrite = expvar.NewInt("connectionWriterWrite")
+var (
+       // Track connection writer buffer writes and flushes, to determine its
+       // efficiency.
+       connectionWriterFlush = expvar.NewInt("connectionWriterFlush")
+       connectionWriterWrite = expvar.NewInt("connectionWriterWrite")
+)
 
 // Writes buffers to the socket from the write channel.
 func (conn *connection) writer() {
        // Reduce write syscalls.
-       buf := bufio.NewWriterSize(conn.rw, 0x8000) // 32 KiB
-       // Receives when buf is not empty.
-       notEmpty := make(chan struct{}, 1)
+       buf := bufio.NewWriter(conn.rw)
        for {
-               if buf.Buffered() != 0 {
-                       // Make sure it's receivable.
+               if buf.Buffered() == 0 {
+                       // There's nothing to write, so block until we get something.
                        select {
-                       case notEmpty <- struct{}{}:
-                       default:
-                       }
-               }
-               select {
-               case b, ok := <-conn.writeCh:
-                       if !ok {
-                               return
-                       }
-                       connectionWriterWrite.Add(1)
-                       _, err := buf.Write(b)
-                       if err != nil {
-                               conn.Close()
+                       case b, ok := <-conn.writeCh:
+                               if !ok {
+                                       return
+                               }
+                               connectionWriterWrite.Add(1)
+                               _, err := buf.Write(b)
+                               if err != nil {
+                                       conn.Close()
+                                       return
+                               }
+                       case <-conn.closing:
                                return
                        }
-               case <-conn.closing:
-                       return
-               case <-notEmpty:
-                       connectionWriterFlush.Add(1)
-                       err := buf.Flush()
-                       if err != nil {
+               } else {
+                       // We already have something to write, so flush if there's nothing
+                       // more to write.
+                       select {
+                       case b, ok := <-conn.writeCh:
+                               if !ok {
+                                       return
+                               }
+                               connectionWriterWrite.Add(1)
+                               _, err := buf.Write(b)
+                               if err != nil {
+                                       conn.Close()
+                                       return
+                               }
+                       case <-conn.closing:
                                return
+                       default:
+                               connectionWriterFlush.Add(1)
+                               err := buf.Flush()
+                               if err != nil {
+                                       conn.Close()
+                                       return
+                               }
                        }
                }
        }