Clone this repo:
  1. 92b4c20 Upgrade to github.com/klauspost/compress v1.16.5, and require go 1.17 by Mostyn Bramley-Moore · 1 year, 2 months ago main v0.0.13
  2. 005d140 Update CI actions by Mostyn Bramley-Moore · 1 year, 2 months ago
  3. e88625d upgrade github.com/klauspost/compress to v1.14.1 by Mostyn Bramley-Moore · 2 years, 6 months ago v0.0.12
  4. b59a8b2 upgrade github.com/klauspost/compress to v1.13.6 by Mostyn Bramley-Moore · 2 years, 9 months ago v0.0.11
  5. 7c77d5c Add simplified wrappers to avoid misuse by Mostyn Bramley-Moore · 2 years, 9 months ago

godoc

zstdpool-syncpool

github.com/klauspost/compress/zstd is a native Go implementation of Zstandard, with an API that leaks memory and goroutines if you don't call Close() on every Encoder and Decoder that you create, and Decoders cannot be reused after they are closed.

zstdpool-syncpool is a Go wrapper for github.com/klauspost/compress/zstd and sync.Pool, which automatically frees resources if you forget to call Close() and/or when items are dropped from the sync.Pool.

Background: https://github.com/klauspost/compress/issues/264

Basic usage

https://pkg.go.dev/github.com/mostynb/zstdpool-syncpool

import (
	"github.com/klauspost/compress/zstd"
	syncpool "github.com/mostynb/zstdpool-syncpool"
)

// Create a sync.Pool which returns wrapped *zstd.Decoder's.
decoderPool := syncpool.NewDecoderPool(zstd.WithDecoderConcurrency(1))

// Get a *DecoderWrapper and use it.
decoder := decoderPool.Get().(*syncpool.DecoderWrapper)
decoder.Reset(compressedDataReader)
_, err = io.Copy(uncompressedDataWriter, decoder)

// Return the decoder to the pool. If we forget this, then the zstd.Decoder
// won't leak resources.
decoderPool.Put(decoder)


// Create a sync.Pool which returns wrapped *zstd.Endoder's.
encoderPool := syncpool.NewEncoderPool(zstd.WithEncoderConcurrency(1))

// Get an *EncoderWrapper and use it.
encoder := encoderPool.Get().(*syncpool.EncoderWrapper)
encoder.Reset(compressedDataWriter)
_, err = io.Copy(encoder, uncompressedDataReader)

// Return the encoder to the pool. If we forget this, then the zstd.Encoder
// won't leak resources.
encoderPool.Put(encoder)

Simplified usage

If you would like to avoid type assertions, you can use NewDecoderPoolWapper and NewEncoderPoolWrapper:

import (
	"github.com/klauspost/compress/zstd"
	syncpool "github.com/mostynb/zstdpool-syncpool"
)

// Create a sync.Pool which returns wrapped *zstd.Decoder's.
decoderPool := syncpool.NewDecoderPoolWrapper(zstd.WithDecoderConcurrency(1))

// Get a *DecoderWrapper and use it.
decoder := decoderPool.Get(compressedDataReader)
_, err = io.Copy(uncompressedDataWriter, decoder)

// Return the decoder to the pool. If we forget this, then the zstd.Decoder
// won't leak resources.
decoderPool.Put(decoder)

// Create a sync.Pool which returns wrapped *zstd.Endoder's.
encoderPool := syncpool.NewEncoderPoolWrapper(zstd.WithEncoderConcurrency(1))

// Get an EncoderWrapper and use it.
encoder := encoderPool.Get(compressedDataWriter)
_, err = io.Copy(encoder, uncompressedDataReader)

// Return the encoder to the pool. If we forget this, then the zstd.Encoder
// won't leak resources.
encoderPool.Put(encoder)

Contributing

Bug reports, feature requests, PRs welcome.

License

Licensed under the Apache License, Version 2.0. See the LICENSE file.