Reviewers: golang-dev_googlegroups.com,
Message:
Hello golang-dev@googlegroups.com (cc: nigeltao@golang.org),
I'd like you to review this change to
https://code.google.com/p/go/
Description:
bufio: Optimize (*Writer).ReadFrom when the buffer is not empty
Please review this at http://codereview.appspot.com/6842078/
Affected files:
M src/pkg/bufio/bufio.go
M src/pkg/bufio/bufio_test.go
Index: src/pkg/bufio/bufio.go
===================================================================
--- a/src/pkg/bufio/bufio.go
+++ b/src/pkg/bufio/bufio.go
@@ -569,32 +569,50 @@
// ReadFrom implements io.ReaderFrom.
func (b *Writer) ReadFrom(r io.Reader) (n int64, err error) {
- if b.Buffered() == 0 {
- if w, ok := b.wr.(io.ReaderFrom); ok {
- return w.ReadFrom(r)
+ //Want to call Write with the most amt of data possible, so
+ // if the buf has data in it, fill it then use ReadFrom instead
+ // of flushing immediately
+ if w, ok := b.wr.(io.ReaderFrom); ok {
+ if b.Buffered() != 0 {
+ //Have data, fill it up & then flush
+ m, err1 := io.ReadFull(r, b.buf[b.n:])
+ b.n += m
+ n += int64(m)
+ if err = b.Flush(); err1 != nil {
+ return
+ }
+ err = err1
+ if err != nil {
+ //Don't care that we didn't read the entire buf, so
+ // unexpected EOF should be treated the same as EOF
+ if err == io.EOF || err == io.ErrUnexpectedEOF {
+ err = nil
+ }
+ return
+ }
}
+ var m int64
+ m, err = w.ReadFrom(r)
+ return n + m, err
}
- var m int
for {
- m, err = r.Read(b.buf[b.n:])
- if m == 0 {
- break
- }
+ m, err1 := io.ReadFull(r, b.buf[b.n:])
b.n += m
n += int64(m)
if b.Available() == 0 {
- if err1 := b.Flush(); err1 != nil {
- return n, err1
+ if err = b.Flush(); err != nil {
+ return
}
}
+ err = err1
if err != nil {
break
}
}
- if err == io.EOF {
+ if err == io.EOF || err == io.ErrUnexpectedEOF {
err = nil
}
- return n, err
+ return
}
// buffered input and output
Index: src/pkg/bufio/bufio_test.go
===================================================================
--- a/src/pkg/bufio/bufio_test.go
+++ b/src/pkg/bufio/bufio_test.go
@@ -856,12 +856,24 @@
expected error
}
-func (r errorReaderFromTest) Read(p []byte) (int, error) {
- return len(p) * r.rn, r.rerr
+func (r *errorReaderFromTest) Read(p []byte) (n int, err error) {
+ n = len(p) * r.rn
+ err = r.rerr
+ if r.rerr != nil {
+ //If we are returning an err this time, all future reads should fail
completely
+ r.rn = 0
+ }
+ return
}
-func (w errorReaderFromTest) Write(p []byte) (int, error) {
- return len(p) * w.wn, w.werr
+func (w *errorReaderFromTest) Write(p []byte) (n int, err error) {
+ n = len(p) * w.wn
+ err = w.werr
+ if w.werr != nil {
+ //If we are returning an err this time, all future writes should fail
completely
+ w.wn = 0
+ }
+ return
}
var errorReaderFromTests = []errorReaderFromTest{
@@ -874,8 +886,8 @@
func TestWriterReadFromErrors(t *testing.T) {
for i, rw := range errorReaderFromTests {
- w := NewWriter(rw)
- if _, err := w.ReadFrom(rw); err != rw.expected {
+ w := NewWriter(&rw)
+ if _, err := w.ReadFrom(&rw); err != rw.expected {
t.Errorf("w.ReadFrom(errorReaderFromTests[%d]) = _, %v, want _,%v", i,
err, rw.expected)
}
}