Commit 9acb87a8 authored by Kirill Smelkov's avatar Kirill Smelkov

X xzlib: Reuse zlib decoders

name                        old time/op    new time/op    delta
deco/unzlib/py/null-1K        2.11µs ± 1%    2.12µs ± 1%     ~     (p=0.690 n=5+5)
deco/unzlib/go/null-1K        5.87µs ± 1%    1.89µs ± 1%  -67.77%  (p=0.008 n=5+5)
deco/unzlib/py/null-4K        13.3µs ± 1%    13.5µs ± 4%     ~     (p=0.690 n=5+5)
deco/unzlib/go/null-4K        12.6µs ± 0%     8.5µs ± 0%  -32.50%  (p=0.008 n=5+5)
deco/unzlib/py/null-2M        5.17ms ±11%    5.20ms ±10%     ~     (p=1.000 n=5+5)
deco/unzlib/go/null-2M        2.61ms ± 1%    2.58ms ± 1%   -1.32%  (p=0.016 n=5+5)
deco/unzlib/py/wczdata-avg    20.9µs ±14%    24.1µs ± 1%  +15.05%  (p=0.016 n=5+4)
deco/unzlib/go/wczdata-avg    73.0µs ± 1%    68.0µs ± 1%   -6.94%  (p=0.008 n=5+5)
deco/unzlib/py/wczdata-max    23.6µs ± 0%    23.5µs ± 1%     ~     (p=0.905 n=5+4)
deco/unzlib/go/wczdata-max    72.7µs ± 0%    67.8µs ± 0%   -6.79%  (p=0.008 n=5+5)
deco/unzlib/py/prod1-avg      4.53µs ± 3%    4.47µs ± 2%     ~     (p=0.310 n=5+5)
deco/unzlib/go/prod1-avg      15.5µs ± 0%    11.0µs ± 0%  -29.11%  (p=0.008 n=5+5)
deco/unzlib/py/prod1-max       327µs ± 1%     326µs ± 0%     ~     (p=1.000 n=5+5)
deco/unzlib/go/prod1-max       545µs ± 0%     542µs ± 0%   -0.68%  (p=0.008 n=5+5)

still on wczdata and prod1 much slower compared to py/c zlib.
parent 924831e7
...@@ -24,6 +24,7 @@ import ( ...@@ -24,6 +24,7 @@ import (
"bytes" "bytes"
"compress/zlib" "compress/zlib"
"io" "io"
"sync"
) )
...@@ -45,6 +46,41 @@ func Compress(data []byte) (zdata []byte) { ...@@ -45,6 +46,41 @@ func Compress(data []byte) (zdata []byte) {
} }
// ---- 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.
...@@ -53,7 +89,7 @@ func Compress(data []byte) (zdata []byte) { ...@@ -53,7 +89,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(in []byte, out []byte) (data []byte, err error) { func Decompress(in []byte, out []byte) (data []byte, err error) {
bin := bytes.NewReader(in) bin := bytes.NewReader(in)
zr, err := zlib.NewReader(bin) zr, err := zlibNewReader(bin)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -63,6 +99,7 @@ func Decompress(in []byte, out []byte) (data []byte, err error) { ...@@ -63,6 +99,7 @@ func Decompress(in []byte, out []byte) (data []byte, err error) {
err = err2 err = err2
data = nil data = nil
} }
zlibFreeReader(zr)
}() }()
bout := bytes.NewBuffer(out) bout := bytes.NewBuffer(out)
......
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