From: Niko Dziemba Date: Wed, 10 Feb 2016 14:57:16 +0000 (+0100) Subject: archive/zip: pool flate readers X-Git-Tag: go1.7beta1~350 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=e155bf0ce8543ebffb3b5a699861402f7abe08d7;p=gostls13.git archive/zip: pool flate readers Similar to the flate Writer pools already used, this adds pooling for flate Readers. compress/flate allows re-using of Readers, see https://codereview.appspot.com/97140043/ In a real-world scenario when reading ~ 500 small files from a ZIP archive this gives a speedup of 1.5x-2x. Fixes #14289 Change-Id: I2d98ad983e95ab7d97e06fd0145f619b4f47caa4 Reviewed-on: https://go-review.googlesource.com/19416 Run-TryBot: Brad Fitzpatrick TryBot-Result: Gobot Gobot Reviewed-by: Brad Fitzpatrick --- diff --git a/src/archive/zip/register.go b/src/archive/zip/register.go index 8fccbf7ca0..2e76386b1f 100644 --- a/src/archive/zip/register.go +++ b/src/archive/zip/register.go @@ -64,6 +64,44 @@ func (w *pooledFlateWriter) Close() error { return err } +var flateReaderPool sync.Pool + +func newFlateReader(r io.Reader) io.ReadCloser { + fr, ok := flateReaderPool.Get().(io.ReadCloser) + if ok { + fr.(flate.Resetter).Reset(r, nil) + } else { + fr = flate.NewReader(r) + } + return &pooledFlateReader{fr: fr} +} + +type pooledFlateReader struct { + mu sync.Mutex // guards Close and Read + fr io.ReadCloser +} + +func (r *pooledFlateReader) Read(p []byte) (n int, err error) { + r.mu.Lock() + defer r.mu.Unlock() + if r.fr == nil { + return 0, errors.New("Read after Close") + } + return r.fr.Read(p) +} + +func (r *pooledFlateReader) Close() error { + r.mu.Lock() + defer r.mu.Unlock() + var err error + if r.fr != nil { + err = r.fr.Close() + flateReaderPool.Put(r.fr) + r.fr = nil + } + return err +} + var ( mu sync.RWMutex // guards compressor and decompressor maps @@ -74,7 +112,7 @@ var ( decompressors = map[uint16]Decompressor{ Store: ioutil.NopCloser, - Deflate: flate.NewReader, + Deflate: newFlateReader, } )