mirror of
https://github.com/kopia/kopia.git
synced 2026-01-28 00:08:04 -05:00
This helps recycle buffers more efficiently during snapshots. Also, improved memory tracking, enabled profiling flags and added pprof by default.
81 lines
1.9 KiB
Go
81 lines
1.9 KiB
Go
package compression
|
|
|
|
import (
|
|
"io"
|
|
"sync"
|
|
|
|
"github.com/klauspost/compress/zstd"
|
|
"github.com/pkg/errors"
|
|
|
|
"github.com/kopia/kopia/internal/iocopy"
|
|
)
|
|
|
|
func init() {
|
|
RegisterCompressor("zstd", newZstdCompressor(headerZstdDefault, zstd.SpeedDefault))
|
|
RegisterCompressor("zstd-fastest", newZstdCompressor(headerZstdFastest, zstd.SpeedFastest))
|
|
RegisterCompressor("zstd-better-compression", newZstdCompressor(headerZstdBetterCompression, zstd.SpeedBetterCompression))
|
|
RegisterCompressor("zstd-best-compression", newZstdCompressor(headerZstdBestCompression, zstd.SpeedBestCompression))
|
|
}
|
|
|
|
func newZstdCompressor(id HeaderID, level zstd.EncoderLevel) Compressor {
|
|
return &zstdCompressor{id, compressionHeader(id), sync.Pool{
|
|
New: func() interface{} {
|
|
w, err := zstd.NewWriter(io.Discard, zstd.WithEncoderLevel(level))
|
|
mustSucceed(err)
|
|
return w
|
|
},
|
|
}}
|
|
}
|
|
|
|
type zstdCompressor struct {
|
|
id HeaderID
|
|
header []byte
|
|
pool sync.Pool
|
|
}
|
|
|
|
func (c *zstdCompressor) HeaderID() HeaderID {
|
|
return c.id
|
|
}
|
|
|
|
func (c *zstdCompressor) Compress(output io.Writer, input io.Reader) error {
|
|
if _, err := output.Write(c.header); err != nil {
|
|
return errors.Wrap(err, "unable to write header")
|
|
}
|
|
|
|
// nolint:forcetypeassert
|
|
w := c.pool.Get().(*zstd.Encoder)
|
|
defer c.pool.Put(w)
|
|
|
|
w.Reset(output)
|
|
|
|
if err := iocopy.JustCopy(w, input); err != nil {
|
|
return errors.Wrap(err, "compression error")
|
|
}
|
|
|
|
if err := w.Close(); err != nil {
|
|
return errors.Wrap(err, "compression close error")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (c *zstdCompressor) Decompress(output io.Writer, input io.Reader, withHeader bool) error {
|
|
if withHeader {
|
|
if err := verifyCompressionHeader(input, c.header); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
r, err := zstd.NewReader(input)
|
|
if err != nil {
|
|
return errors.Wrap(err, "unable to open zstd stream")
|
|
}
|
|
defer r.Close()
|
|
|
|
if err := iocopy.JustCopy(output, r); err != nil {
|
|
return errors.Wrap(err, "decompression error")
|
|
}
|
|
|
|
return nil
|
|
}
|