mirror of https://github.com/pkg/sftp.git
perf: ensure full write buffer for *File.ReadFrom
In `*File.ReadFrom`, ensure that the buffer is filled to capacity (`maxPacket` length) before performing the write. Prior to this change, the amount of data read into the buffer was dictated by the `io.Reader`'s `Read` implementation, and write performance would suffer when the Read would return less than maxPacket bytes of data. An example source would be a `net/http` response `Body` from a TLS server, which seems to cap each read to 16384 bytes -- half the default max packet size of 32768 bytes.
This commit is contained in:
parent
19bfb49e71
commit
28eb389db7
10
client.go
10
client.go
|
@ -1842,7 +1842,8 @@ func (f *File) readFromWithConcurrency(r io.Reader, concurrency int) (read int64
|
||||||
off := f.offset
|
off := f.offset
|
||||||
|
|
||||||
for {
|
for {
|
||||||
n, err := r.Read(b)
|
// Fill the entire buffer.
|
||||||
|
n, err := io.ReadFull(r, b)
|
||||||
|
|
||||||
if n > 0 {
|
if n > 0 {
|
||||||
read += int64(n)
|
read += int64(n)
|
||||||
|
@ -1868,7 +1869,7 @@ func (f *File) readFromWithConcurrency(r io.Reader, concurrency int) (read int64
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err != io.EOF {
|
if !errors.Is(err, io.EOF) && !errors.Is(err, io.ErrUnexpectedEOF) {
|
||||||
errCh <- rwErr{off, err}
|
errCh <- rwErr{off, err}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
@ -2022,7 +2023,8 @@ func (f *File) ReadFrom(r io.Reader) (int64, error) {
|
||||||
|
|
||||||
var read int64
|
var read int64
|
||||||
for {
|
for {
|
||||||
n, err := r.Read(b)
|
// Fill the entire buffer.
|
||||||
|
n, err := io.ReadFull(r, b)
|
||||||
if n < 0 {
|
if n < 0 {
|
||||||
panic("sftp.File: reader returned negative count from Read")
|
panic("sftp.File: reader returned negative count from Read")
|
||||||
}
|
}
|
||||||
|
@ -2039,7 +2041,7 @@ func (f *File) ReadFrom(r io.Reader) (int64, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == io.EOF {
|
if errors.Is(err, io.EOF) || errors.Is(err, io.ErrUnexpectedEOF) {
|
||||||
return read, nil // return nil explicitly.
|
return read, nil // return nil explicitly.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue