* Added basic structure for compression Signed-off-by: Joe Elliott <[email protected]> * AppenderBuffered impl Signed-off-by: Joe Elliott <[email protected]> * mild commenting Signed-off-by: Joe Elliott <[email protected]> * moved encoding to meta json Signed-off-by: Joe Elliott <[email protected]> * Added pagedReader and backend.ReaderAt Signed-off-by: Joe Elliott <[email protected]> * dedupingfinder => pagedfinder Signed-off-by: Joe Elliott <[email protected]> * Abstracted away index reading. Used pagedFinder in backend block Signed-off-by: Joe Elliott <[email protected]> * Abstracted PagedIterator to use indexReader Signed-off-by: Joe Elliott <[email protected]> * improved comments Signed-off-by: Joe Elliott <[email protected]> * created versioned encoding Signed-off-by: Joe Elliott <[email protected]> * removed findmetrics Signed-off-by: Joe Elliott <[email protected]> * Moved backend block to encoding Signed-off-by: Joe Elliott <[email protected]> * Moved indexreader records to common Signed-off-by: Joe Elliott <[email protected]> * Added index reader Signed-off-by: Joe Elliott <[email protected]> * jpe cleanup Signed-off-by: Joe Elliott <[email protected]> * v1 LIVES Signed-off-by: Joe Elliott <[email protected]> * Tests pass on v1 Signed-off-by: Joe Elliott <[email protected]> * encoding tests pass Signed-off-by: Joe Elliott <[email protected]> * wooo snappy tests Signed-off-by: Joe Elliott <[email protected]> * Moved block config to its own struct Signed-off-by: Joe Elliott <[email protected]> * Add custom marshaller Signed-off-by: Joe Elliott <[email protected]> * updated configs added default Signed-off-by: Joe Elliott <[email protected]> * Test all encodings Signed-off-by: Joe Elliott <[email protected]> * Added benchmark. Default to snappy Signed-off-by: Joe Elliott <[email protected]> * fixed panic in reader Signed-off-by: Joe Elliott <[email protected]> * Fleshed out benchmarks Signed-off-by: Joe Elliott <[email protected]> * lint Signed-off-by: Joe Elliott <[email protected]> * backend_block => benchmark_block Signed-off-by: Joe Elliott <[email protected]> * Added 256 and 1M LZ4 tests Signed-off-by: Joe Elliott <[email protected]> * Removed findmetrics from operational Signed-off-by: Joe Elliott <[email protected]> * indexreaderbytes => indexreader Signed-off-by: Joe Elliott <[email protected]> * jpe cleanup Signed-off-by: Joe Elliott <[email protected]> * Fixed bytes flushed metric Signed-off-by: Joe Elliott <[email protected]> * Changed default encoding Signed-off-by: Joe Elliott <[email protected]> * Pass tracker correctly. Add guard code Signed-off-by: Joe Elliott <[email protected]> * Added marshal tests Signed-off-by: Joe Elliott <[email protected]> * lint Signed-off-by: Joe Elliott <[email protected]> * page reader tests Signed-off-by: Joe Elliott <[email protected]> * actually add tests Signed-off-by: Joe Elliott <[email protected]> * Added reader tess Signed-off-by: Joe Elliott <[email protected]> * changelog Signed-off-by: Joe Elliott <[email protected]> * zstd Signed-off-by: Joe Elliott <[email protected]> * vendor Signed-off-by: Joe Elliott <[email protected]>
4.5 KiB
Finite State Entropy
This package provides Finite State Entropy encoding and decoding.
Finite State Entropy (also referenced as tANS) encoding provides a fast near-optimal symbol encoding/decoding for byte blocks as implemented in zstandard.
This can be used for compressing input with a lot of similar input values to the smallest number of bytes. This does not perform any multi-byte dictionary coding as LZ coders, but it can be used as a secondary step to compressors (like Snappy) that does not do entropy encoding.
News
- Feb 2018: First implementation released. Consider this beta software for now.
Usage
This package provides a low level interface that allows to compress single independent blocks.
Each block is separate, and there is no built in integrity checks. This means that the caller should keep track of block sizes and also do checksums if needed.
Compressing a block is done via the Compress function.
You must provide input and will receive the output and maybe an error.
These error values can be returned:
| Error | Description |
|---|---|
<nil> |
Everything ok, output is returned |
ErrIncompressible |
Returned when input is judged to be too hard to compress |
ErrUseRLE |
Returned from the compressor when the input is a single byte value repeated |
(error) |
An internal error occurred. |
As can be seen above there are errors that will be returned even under normal operation so it is important to handle these.
To reduce allocations you can provide a Scratch object
that can be re-used for successive calls. Both compression and decompression accepts a Scratch object, and the same
object can be used for both.
Be aware, that when re-using a Scratch object that the output buffer is also re-used, so if you are still using this
you must set the Out field in the scratch to nil. The same buffer is used for compression and decompression output.
Decompressing is done by calling the Decompress function.
You must provide the output from the compression stage, at exactly the size you got back. If you receive an error back
your input was likely corrupted.
It is important to note that a successful decoding does not mean your output matches your original input. There are no integrity checks, so relying on errors from the decompressor does not assure your data is valid.
For more detailed usage, see examples in the godoc documentation.
Performance
A lot of factors are affecting speed. Block sizes and compressibility of the material are primary factors.
All compression functions are currently only running on the calling goroutine so only one core will be used per block.
The compressor is significantly faster if symbols are kept as small as possible. The highest byte value of the input is used to reduce some of the processing, so if all your input is above byte value 64 for instance, it may be beneficial to transpose all your input values down by 64.
With moderate block sizes around 64k speed are typically 200MB/s per core for compression and around 300MB/s decompression speed.
The same hardware typically does Huffman (deflate) encoding at 125MB/s and decompression at 100MB/s.
Plans
At one point, more internals will be exposed to facilitate more "expert" usage of the components.
A streaming interface is also likely to be implemented. Likely compatible with FSE stream format.
Contributing
Contributions are always welcome. Be aware that adding public functions will require good justification and breaking changes will likely not be accepted. If in doubt open an issue before writing the PR.