Skip to content

Commit cc3785c

Browse files
authored
Merge pull request containerd#4653 from amrmahdi/amrh/optimize-content-transfer
Improve image pull performance from http 1.1 container registries
2 parents 1c98aa5 + b81917e commit cc3785c

1 file changed

Lines changed: 41 additions & 3 deletions

File tree

content/helpers.go

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -229,9 +229,47 @@ func seekReader(r io.Reader, offset, size int64) (io.Reader, error) {
229229
return r, nil
230230
}
231231

232+
// copyWithBuffer is very similar to io.CopyBuffer https://golang.org/pkg/io/#CopyBuffer
233+
// but instead of using Read to read from the src, we use ReadAtLeast to make sure we have
234+
// a full buffer before we do a write operation to dst to reduce overheads associated
235+
// with the write operations of small buffers.
232236
func copyWithBuffer(dst io.Writer, src io.Reader) (written int64, err error) {
233-
buf := bufPool.Get().(*[]byte)
234-
written, err = io.CopyBuffer(dst, src, *buf)
235-
bufPool.Put(buf)
237+
// If the reader has a WriteTo method, use it to do the copy.
238+
// Avoids an allocation and a copy.
239+
if wt, ok := src.(io.WriterTo); ok {
240+
return wt.WriteTo(dst)
241+
}
242+
// Similarly, if the writer has a ReadFrom method, use it to do the copy.
243+
if rt, ok := dst.(io.ReaderFrom); ok {
244+
return rt.ReadFrom(src)
245+
}
246+
bufRef := bufPool.Get().(*[]byte)
247+
defer bufPool.Put(bufRef)
248+
buf := *bufRef
249+
for {
250+
nr, er := io.ReadAtLeast(src, buf, len(buf))
251+
if nr > 0 {
252+
nw, ew := dst.Write(buf[0:nr])
253+
if nw > 0 {
254+
written += int64(nw)
255+
}
256+
if ew != nil {
257+
err = ew
258+
break
259+
}
260+
if nr != nw {
261+
err = io.ErrShortWrite
262+
break
263+
}
264+
}
265+
if er != nil {
266+
// If an EOF happens after reading fewer than the requested bytes,
267+
// ReadAtLeast returns ErrUnexpectedEOF.
268+
if er != io.EOF && er != io.ErrUnexpectedEOF {
269+
err = er
270+
}
271+
break
272+
}
273+
}
236274
return
237275
}

0 commit comments

Comments
 (0)