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:
Mike Ryan 2025-03-23 15:37:04 -05:00
parent 19bfb49e71
commit 28eb389db7
1 changed files with 6 additions and 4 deletions

View File

@ -1842,7 +1842,8 @@ func (f *File) readFromWithConcurrency(r io.Reader, concurrency int) (read int64
off := f.offset
for {
n, err := r.Read(b)
// Fill the entire buffer.
n, err := io.ReadFull(r, b)
if n > 0 {
read += int64(n)
@ -1868,7 +1869,7 @@ func (f *File) readFromWithConcurrency(r io.Reader, concurrency int) (read int64
}
if err != nil {
if err != io.EOF {
if !errors.Is(err, io.EOF) && !errors.Is(err, io.ErrUnexpectedEOF) {
errCh <- rwErr{off, err}
}
return
@ -2022,7 +2023,8 @@ func (f *File) ReadFrom(r io.Reader) (int64, error) {
var read int64
for {
n, err := r.Read(b)
// Fill the entire buffer.
n, err := io.ReadFull(r, b)
if n < 0 {
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 == io.EOF {
if errors.Is(err, io.EOF) || errors.Is(err, io.ErrUnexpectedEOF) {
return read, nil // return nil explicitly.
}