Commit fc44cbd7 authored by Kirill Smelkov's avatar Kirill Smelkov

go/internal/xzlib: Try to reuse zlib decoders

name                 old time/op    new time/op    delta
unzlib/py/wczdata      20.7µs ± 2%    20.8µs ± 2%     ~     (p=0.548 n=5+5)
unzlib/go/wczdata      70.6µs ± 0%    64.4µs ± 1%   -8.85%  (p=0.008 n=5+5)
unzlib/py/prod1-avg    4.02µs ± 1%    4.00µs ± 1%     ~     (p=0.167 n=5+5)
unzlib/go/prod1-avg    15.2µs ± 0%    10.4µs ± 1%  -31.59%  (p=0.008 n=5+5)

still on wczdata and prod1 much slower compared to py/c zlib.
parent 91a8afa8
...@@ -24,6 +24,7 @@ import ( ...@@ -24,6 +24,7 @@ import (
"bytes" "bytes"
"compress/zlib" "compress/zlib"
"io" "io"
"sync"
) )
// Compress compresses data according to zlib encoding. // Compress compresses data according to zlib encoding.
...@@ -43,6 +44,41 @@ func Compress(data []byte) (zdata []byte) { ...@@ -43,6 +44,41 @@ func Compress(data []byte) (zdata []byte) {
return b.Bytes() return b.Bytes()
} }
// ---- zlib.Reader pool ----
// (creating zlib.NewReader for every decompress has high overhead for not large blocks)
// znull is a small valid zlib stream.
// we need it to create new zlib readers under sync.Pool .
var znull = Compress(nil)
var zrPool = sync.Pool{New: func() interface{} {
r, err := zlib.NewReader(bytes.NewReader(znull))
if err != nil {
panic(err) // must not happen - znull is valid stream
}
return r
}}
// interface actually implemented by what zlib.NewReader returns
type zlibReader interface {
io.ReadCloser
zlib.Resetter
}
func zlibNewReader(r io.Reader) (zlibReader, error) {
zr := zrPool.Get().(zlibReader)
err := zr.Reset(r, nil)
if err != nil {
zlibFreeReader(zr)
return nil, err
}
return zr, nil
}
func zlibFreeReader(r zlibReader) {
zrPool.Put(r)
}
// Decompress decompresses data according to zlib encoding. // Decompress decompresses data according to zlib encoding.
// //
// out buffer, if there is enough capacity, is used for decompression destination. // out buffer, if there is enough capacity, is used for decompression destination.
...@@ -51,7 +87,7 @@ func Compress(data []byte) (zdata []byte) { ...@@ -51,7 +87,7 @@ func Compress(data []byte) (zdata []byte) {
// return: destination buffer with full decompressed data or error. // return: destination buffer with full decompressed data or error.
func Decompress(zdata []byte, out []byte) (data []byte, err error) { func Decompress(zdata []byte, out []byte) (data []byte, err error) {
bin := bytes.NewReader(zdata) bin := bytes.NewReader(zdata)
zr, err := zlib.NewReader(bin) zr, err := zlibNewReader(bin)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -61,6 +97,7 @@ func Decompress(zdata []byte, out []byte) (data []byte, err error) { ...@@ -61,6 +97,7 @@ func Decompress(zdata []byte, out []byte) (data []byte, err error) {
err = err2 err = err2
data = nil data = nil
} }
zlibFreeReader(zr)
}() }()
bout := bytes.NewBuffer(out[:0]) bout := bytes.NewBuffer(out[:0])
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment