Commit 34fd5db1 authored by Bryan C. Mills's avatar Bryan C. Mills Committed by Brad Fitzpatrick

archive/zip: replace RWMutex with sync.Map

This change replaces the compressors and decompressors maps with
instances of sync.Map, eliminating the need for Mutex locking in
NewReader and NewWriter.

The impact for encoding large payloads is miniscule, but as the
payload size decreases, the reduction in setup costs becomes
measurable.

updates #17973
updates #18177

name                        old time/op    new time/op    delta
CompressedZipGarbage          13.6ms ± 3%    13.8ms ± 4%    ~     (p=0.275 n=14+16)
CompressedZipGarbage-6        2.81ms ±10%    2.80ms ± 9%    ~     (p=0.616 n=16+16)
CompressedZipGarbage-48        606µs ± 4%     600µs ± 3%    ~     (p=0.110 n=16+15)
Zip64Test                     88.7ms ± 5%    87.5ms ± 5%    ~     (p=0.150 n=14+14)
Zip64Test-6                   88.6ms ± 8%    94.5ms ±13%    ~     (p=0.070 n=14+16)
Zip64Test-48                   102ms ±19%     101ms ±19%    ~     (p=0.599 n=16+15)
Zip64TestSizes/4096           21.7µs ±10%    23.0µs ± 2%    ~     (p=0.076 n=14+12)
Zip64TestSizes/4096-6         7.58µs ±13%    7.49µs ±18%    ~     (p=0.752 n=16+16)
Zip64TestSizes/4096-48        19.5µs ± 8%    18.0µs ± 4%  -7.74%  (p=0.000 n=16+15)
Zip64TestSizes/1048576        1.36ms ± 9%    1.40ms ± 8%  +2.79%  (p=0.029 n=24+25)
Zip64TestSizes/1048576-6       262µs ±11%     260µs ±10%    ~     (p=0.506 n=24+24)
Zip64TestSizes/1048576-48      120µs ± 7%     116µs ± 7%  -3.05%  (p=0.006 n=24+25)
Zip64TestSizes/67108864       86.8ms ± 6%    85.1ms ± 5%    ~     (p=0.149 n=14+17)
Zip64TestSizes/67108864-6     15.9ms ± 2%    16.1ms ± 6%    ~     (p=0.279 n=14+17)
Zip64TestSizes/67108864-48    4.51ms ± 5%    4.53ms ± 4%    ~     (p=0.766 n=15+17)

name                        old alloc/op   new alloc/op   delta
CompressedZipGarbage          5.63kB ± 0%    5.63kB ± 0%    ~     (all equal)
CompressedZipGarbage-6        15.4kB ± 0%    15.4kB ± 0%    ~     (all equal)
CompressedZipGarbage-48       25.5kB ± 3%    25.6kB ± 2%    ~     (p=0.450 n=16+16)
Zip64Test                     20.0kB ± 0%    20.0kB ± 0%    ~     (p=0.060 n=16+13)
Zip64Test-6                   20.0kB ± 0%    20.0kB ± 0%    ~     (p=0.136 n=16+14)
Zip64Test-48                  20.0kB ± 0%    20.0kB ± 0%    ~     (p=1.000 n=16+16)
Zip64TestSizes/4096           20.0kB ± 0%    20.0kB ± 0%    ~     (all equal)
Zip64TestSizes/4096-6         20.0kB ± 0%    20.0kB ± 0%    ~     (all equal)
Zip64TestSizes/4096-48        20.0kB ± 0%    20.0kB ± 0%  -0.00%  (p=0.002 n=16+13)
Zip64TestSizes/1048576        20.0kB ± 0%    20.0kB ± 0%    ~     (all equal)
Zip64TestSizes/1048576-6      20.0kB ± 0%    20.0kB ± 0%    ~     (all equal)
Zip64TestSizes/1048576-48     20.1kB ± 0%    20.1kB ± 0%    ~     (p=0.775 n=24+25)
Zip64TestSizes/67108864       20.0kB ± 0%    20.0kB ± 0%    ~     (all equal)
Zip64TestSizes/67108864-6     20.0kB ± 0%    20.0kB ± 0%    ~     (p=0.272 n=16+17)
Zip64TestSizes/67108864-48    20.1kB ± 0%    20.1kB ± 0%    ~     (p=0.098 n=14+15)

name                        old allocs/op  new allocs/op  delta
CompressedZipGarbage            44.0 ± 0%      44.0 ± 0%    ~     (all equal)
CompressedZipGarbage-6          44.0 ± 0%      44.0 ± 0%    ~     (all equal)
CompressedZipGarbage-48         44.0 ± 0%      44.0 ± 0%    ~     (all equal)
Zip64Test                       53.0 ± 0%      53.0 ± 0%    ~     (all equal)
Zip64Test-6                     53.0 ± 0%      53.0 ± 0%    ~     (all equal)
Zip64Test-48                    53.0 ± 0%      53.0 ± 0%    ~     (all equal)
Zip64TestSizes/4096             53.0 ± 0%      53.0 ± 0%    ~     (all equal)
Zip64TestSizes/4096-6           53.0 ± 0%      53.0 ± 0%    ~     (all equal)
Zip64TestSizes/4096-48          53.0 ± 0%      53.0 ± 0%    ~     (all equal)
Zip64TestSizes/1048576          53.0 ± 0%      53.0 ± 0%    ~     (all equal)
Zip64TestSizes/1048576-6        53.0 ± 0%      53.0 ± 0%    ~     (all equal)
Zip64TestSizes/1048576-48       53.0 ± 0%      53.0 ± 0%    ~     (all equal)
Zip64TestSizes/67108864         53.0 ± 0%      53.0 ± 0%    ~     (all equal)
Zip64TestSizes/67108864-6       53.0 ± 0%      53.0 ± 0%    ~     (all equal)
Zip64TestSizes/67108864-48      53.0 ± 0%      53.0 ± 0%    ~     (all equal)

https://perf.golang.org/search?q=upload:20170428.4

Change-Id: Idb7bec091a210aba833066f8d083d66e27788286
Reviewed-on: https://go-review.googlesource.com/42113
Run-TryBot: Bryan Mills <bcmills@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarBrad Fitzpatrick <bradfitz@golang.org>
parent e5c9358f
......@@ -103,51 +103,46 @@ func (r *pooledFlateReader) Close() error {
}
var (
mu sync.RWMutex // guards compressor and decompressor maps
compressors sync.Map // map[uint16]Compressor
decompressors sync.Map // map[uint16]Decompressor
)
compressors = map[uint16]Compressor{
Store: func(w io.Writer) (io.WriteCloser, error) { return &nopCloser{w}, nil },
Deflate: func(w io.Writer) (io.WriteCloser, error) { return newFlateWriter(w), nil },
}
func init() {
compressors.Store(Store, Compressor(func(w io.Writer) (io.WriteCloser, error) { return &nopCloser{w}, nil }))
compressors.Store(Deflate, Compressor(func(w io.Writer) (io.WriteCloser, error) { return newFlateWriter(w), nil }))
decompressors = map[uint16]Decompressor{
Store: ioutil.NopCloser,
Deflate: newFlateReader,
}
)
decompressors.Store(Store, Decompressor(ioutil.NopCloser))
decompressors.Store(Deflate, Decompressor(newFlateReader))
}
// RegisterDecompressor allows custom decompressors for a specified method ID.
// The common methods Store and Deflate are built in.
func RegisterDecompressor(method uint16, dcomp Decompressor) {
mu.Lock()
defer mu.Unlock()
if _, ok := decompressors[method]; ok {
if _, dup := decompressors.LoadOrStore(method, dcomp); dup {
panic("decompressor already registered")
}
decompressors[method] = dcomp
}
// RegisterCompressor registers custom compressors for a specified method ID.
// The common methods Store and Deflate are built in.
func RegisterCompressor(method uint16, comp Compressor) {
mu.Lock()
defer mu.Unlock()
if _, ok := compressors[method]; ok {
if _, dup := compressors.LoadOrStore(method, comp); dup {
panic("compressor already registered")
}
compressors[method] = comp
}
func compressor(method uint16) Compressor {
mu.RLock()
defer mu.RUnlock()
return compressors[method]
ci, ok := compressors.Load(method)
if !ok {
return nil
}
return ci.(Compressor)
}
func decompressor(method uint16) Decompressor {
mu.RLock()
defer mu.RUnlock()
return decompressors[method]
di, ok := decompressors.Load(method)
if !ok {
return nil
}
return di.(Decompressor)
}
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