From: Matt Joiner Date: Sun, 2 Aug 2015 10:39:31 +0000 (+1000) Subject: connection.writer wasn't working efficiently X-Git-Tag: v1.0.0~1101 X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;h=1cc50f85a6dbd1ca6a5f6e59c30b2f952cf8a923;p=btrtrc.git connection.writer wasn't working efficiently 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. --- diff --git a/connection.go b/connection.go index 1d70c7a7..ba0d124a 100644 --- a/connection.go +++ b/connection.go @@ -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 + } } } }