@@ -13,6 +13,7 @@ import (
13
13
"errors"
14
14
"fmt"
15
15
"io"
16
+ "sync"
16
17
17
18
"github.com/klauspost/compress/flate"
18
19
"github.com/klauspost/compress/zlib"
@@ -371,21 +372,22 @@ func Decompress(dst []byte, src io.Reader) error {
371
372
lr := & io.LimitedReader {R : src , N : srcsz }
372
373
switch kindOf (hdr ) {
373
374
case ZLIB :
374
- rc , err := zlib . NewReader (lr )
375
+ rc , err := zlibNewReader (lr )
375
376
if err != nil {
376
377
return fmt .Errorf ("rcompress: could not create ZLIB reader: %w" , err )
377
378
}
378
- defer rc .Close ()
379
-
380
379
_ , err = io .ReadFull (rc , dst [beg :end ])
380
+ rc .Close ()
381
+ zlibReaderPool .Put (rc )
381
382
if err != nil {
382
383
return fmt .Errorf ("rcompress: could not decompress ZLIB buffer: %w" , err )
383
384
}
384
385
385
386
case LZ4 :
386
- src := make ([] byte , srcsz )
387
+ src := lz4NewBuffer ( srcsz )
387
388
_ , err = io .ReadFull (lr , src )
388
389
if err != nil {
390
+ lz4BufferPool .Put (src )
389
391
return fmt .Errorf ("rcompress: could not read LZ4 block: %w" , err )
390
392
}
391
393
const chksum = 8
@@ -396,7 +398,9 @@ func Decompress(dst []byte, src io.Reader) error {
396
398
case srcsz > tgtsz :
397
399
// no compression
398
400
copy (dst [beg :end ], src [chksum :])
401
+ lz4BufferPool .Put (src )
399
402
default :
403
+ lz4BufferPool .Put (src )
400
404
return fmt .Errorf ("rcompress: could not decompress LZ4 block: %w" , err )
401
405
}
402
406
}
@@ -419,11 +423,13 @@ func Decompress(dst []byte, src io.Reader) error {
419
423
}
420
424
421
425
case ZSTD :
422
- rc , err := zstd . NewReader (lr )
426
+ rc , err := zstdNewReader (lr )
423
427
if err != nil {
424
428
return fmt .Errorf ("rcompress: could not create ZSTD reader: %w" , err )
425
429
}
426
430
_ , err = io .ReadFull (rc , dst [beg :end ])
431
+ rc .Reset (nil )
432
+ zstdReaderPool .Put (rc )
427
433
if err != nil {
428
434
return fmt .Errorf ("rcompress: could not decompress ZSTD block: %w" , err )
429
435
}
@@ -457,3 +463,38 @@ func (w *wbuff) Write(p []byte) (int, error) {
457
463
var (
458
464
_ io.Writer = (* wbuff )(nil )
459
465
)
466
+
467
+ // TODO writers, need to index by options (e.g. compression level)
468
+ var (
469
+ lz4BufferPool = sync.Pool {}
470
+ zlibReaderPool = sync.Pool {}
471
+ zstdReaderPool = sync.Pool {}
472
+ )
473
+
474
+ func lz4NewBuffer (size int64 ) []byte {
475
+ var b []byte
476
+ if bi := lz4BufferPool .Get (); bi != nil {
477
+ b = bi .([]byte )
478
+ }
479
+ if int64 (cap (b )) >= size {
480
+ return b [:size ]
481
+ }
482
+ return make ([]byte , size )
483
+ }
484
+
485
+ func zlibNewReader (r io.Reader ) (io.ReadCloser , error ) {
486
+ if ri := zlibReaderPool .Get (); ri != nil {
487
+ ri .(zlib.Resetter ).Reset (r , nil )
488
+ return ri .(io.ReadCloser ), nil
489
+ }
490
+ return zlib .NewReader (r )
491
+ }
492
+
493
+ func zstdNewReader (r io.Reader ) (* zstd.Decoder , error ) {
494
+ if ri := zstdReaderPool .Get (); ri != nil {
495
+ rd := ri .(* zstd.Decoder )
496
+ rd .Reset (r )
497
+ return rd , nil
498
+ }
499
+ return zstd .NewReader (r )
500
+ }
0 commit comments