• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..21-May-2021-

_generate/H21-May-2021-2,5821,886

cmd/H21-May-2021-1,8061,512

testdata/H03-May-2022-

.gitignoreH A D21-May-2021337 1614

LICENSEH A D21-May-20211.5 KiB2925

README.mdH A D21-May-202134.1 KiB629469

decode.goH A D21-May-202113 KiB521412

decode_amd64.sH A D21-May-202114.3 KiB572244

decode_arm64.sH A D21-May-202114.6 KiB575244

decode_asm.goH A D21-May-2021416 172

decode_other.goH A D21-May-20217 KiB264210

decode_test.goH A D21-May-20213.5 KiB162144

encode.goH A D21-May-202127.2 KiB1,025705

encode_all.goH A D21-May-20216.7 KiB272187

encode_amd64.goH A D21-May-20212.7 KiB10767

encode_best.goH A D21-May-20218.6 KiB339251

encode_better.goH A D21-May-20216.3 KiB241162

encode_go.goH A D21-May-202111.1 KiB461333

encode_test.goH A D21-May-20217 KiB306276

encodeblock_amd64.goH A D21-May-20215.2 KiB14920

encodeblock_amd64.sH A D21-May-2021328.3 KiB13,02211,418

s2.goH A D21-May-20214.4 KiB13755

s2_test.goH A D21-May-202149.1 KiB1,9421,753

README.md

1# S2 Compression
2
3S2 is an extension of [Snappy](https://github.com/google/snappy).
4
5S2 is aimed for high throughput, which is why it features concurrent compression for bigger payloads.
6
7Decoding is compatible with Snappy compressed content, but content compressed with S2 cannot be decompressed by Snappy.
8This means that S2 can seamlessly replace Snappy without converting compressed content.
9
10S2 is designed to have high throughput on content that cannot be compressed.
11This is important, so you don't have to worry about spending CPU cycles on already compressed data.
12
13## Benefits over Snappy
14
15* Better compression
16* Concurrent stream compression
17* Faster decompression
18* Ability to quickly skip forward in compressed stream
19* Compatible with reading Snappy compressed content
20* Offers alternative, more efficient, but slightly slower compression mode.
21* Smaller block size overhead on incompressible blocks.
22* Block concatenation
23* Automatic stream size padding.
24* Snappy compatible block compression.
25
26## Drawbacks over Snappy
27
28* Not optimized for 32 bit systems.
29* Uses slightly more memory (4MB per core) due to larger blocks and concurrency (configurable).
30
31# Usage
32
33Installation: `go get -u github.com/klauspost/compress/s2`
34
35Full package documentation:
36
37[![godoc][1]][2]
38
39[1]: https://godoc.org/github.com/klauspost/compress?status.svg
40[2]: https://godoc.org/github.com/klauspost/compress/s2
41
42## Compression
43
44```Go
45func EncodeStream(src io.Reader, dst io.Writer) error {
46    enc := s2.NewWriter(dst)
47    _, err := io.Copy(enc, src)
48    if err != nil {
49        enc.Close()
50        return err
51    }
52    // Blocks until compression is done.
53    return enc.Close()
54}
55```
56
57You should always call `enc.Close()`, otherwise you will leak resources and your encode will be incomplete.
58
59For the best throughput, you should attempt to reuse the `Writer` using the `Reset()` method.
60
61The Writer in S2 is always buffered, therefore `NewBufferedWriter` in Snappy can be replaced with `NewWriter` in S2.
62It is possible to flush any buffered data using the `Flush()` method.
63This will block until all data sent to the encoder has been written to the output.
64
65S2 also supports the `io.ReaderFrom` interface, which will consume all input from a reader.
66
67As a final method to compress data, if you have a single block of data you would like to have encoded as a stream,
68a slightly more efficient method is to use the `EncodeBuffer` method.
69This will take ownership of the buffer until the stream is closed.
70
71```Go
72func EncodeStream(src []byte, dst io.Writer) error {
73    enc := s2.NewWriter(dst)
74    // The encoder owns the buffer until Flush or Close is called.
75    err := enc.EncodeBuffer(buf)
76    if err != nil {
77        enc.Close()
78        return err
79    }
80    // Blocks until compression is done.
81    return enc.Close()
82}
83```
84
85Each call to `EncodeBuffer` will result in discrete blocks being created without buffering,
86so it should only be used a single time per stream.
87If you need to write several blocks, you should use the regular io.Writer interface.
88
89
90## Decompression
91
92```Go
93func DecodeStream(src io.Reader, dst io.Writer) error {
94    dec := s2.NewReader(src)
95    _, err := io.Copy(dst, dec)
96    return err
97}
98```
99
100Similar to the Writer, a Reader can be reused using the `Reset` method.
101
102For the best possible throughput, there is a `EncodeBuffer(buf []byte)` function available.
103However, it requires that the provided buffer isn't used after it is handed over to S2 and until the stream is flushed or closed.
104
105For smaller data blocks, there is also a non-streaming interface: `Encode()`, `EncodeBetter()` and `Decode()`.
106Do however note that these functions (similar to Snappy) does not provide validation of data,
107so data corruption may be undetected. Stream encoding provides CRC checks of data.
108
109It is possible to efficiently skip forward in a compressed stream using the `Skip()` method.
110For big skips the decompressor is able to skip blocks without decompressing them.
111
112## Single Blocks
113
114Similar to Snappy S2 offers single block compression.
115Blocks do not offer the same flexibility and safety as streams,
116but may be preferable for very small payloads, less than 100K.
117
118Using a simple `dst := s2.Encode(nil, src)` will compress `src` and return the compressed result.
119It is possible to provide a destination buffer.
120If the buffer has a capacity of `s2.MaxEncodedLen(len(src))` it will be used.
121If not a new will be allocated.
122
123Alternatively `EncodeBetter`/`EncodeBest` can also be used for better, but slightly slower compression.
124
125Similarly to decompress a block you can use `dst, err := s2.Decode(nil, src)`.
126Again an optional destination buffer can be supplied.
127The `s2.DecodedLen(src)` can be used to get the minimum capacity needed.
128If that is not satisfied a new buffer will be allocated.
129
130Block function always operate on a single goroutine since it should only be used for small payloads.
131
132# Commandline tools
133
134Some very simply commandline tools are provided; `s2c` for compression and `s2d` for decompression.
135
136Binaries can be downloaded on the [Releases Page](https://github.com/klauspost/compress/releases).
137
138Installing then requires Go to be installed. To install them, use:
139
140`go install github.com/klauspost/compress/s2/cmd/s2c && go install github.com/klauspost/compress/s2/cmd/s2d`
141
142To build binaries to the current folder use:
143
144`go build github.com/klauspost/compress/s2/cmd/s2c && go build github.com/klauspost/compress/s2/cmd/s2d`
145
146
147## s2c
148
149```
150Usage: s2c [options] file1 file2
151
152Compresses all files supplied as input separately.
153Output files are written as 'filename.ext.s2'.
154By default output files will be overwritten.
155Use - as the only file name to read from stdin and write to stdout.
156
157Wildcards are accepted: testdir/*.txt will compress all files in testdir ending with .txt
158Directories can be wildcards as well. testdir/*/*.txt will match testdir/subdir/b.txt
159
160File names beginning with 'http://' and 'https://' will be downloaded and compressed.
161Only http response code 200 is accepted.
162
163Options:
164  -bench int
165    	Run benchmark n times. No output will be written
166  -blocksize string
167    	Max  block size. Examples: 64K, 256K, 1M, 4M. Must be power of two and <= 4MB (default "4M")
168  -c	Write all output to stdout. Multiple input files will be concatenated
169  -cpu int
170    	Compress using this amount of threads (default 32)
171  -faster
172    	Compress faster, but with a minor compression loss
173  -help
174    	Display help
175  -pad string
176    	Pad size to a multiple of this value, Examples: 500, 64K, 256K, 1M, 4M, etc (default "1")
177  -q	Don't write any output to terminal, except errors
178  -rm
179    	Delete source file(s) after successful compression
180  -safe
181    	Do not overwrite output files
182  -slower
183    	Compress more, but a lot slower
184  -verify
185    	Verify written files
186
187```
188
189## s2d
190
191```
192Usage: s2d [options] file1 file2
193
194Decompresses all files supplied as input. Input files must end with '.s2' or '.snappy'.
195Output file names have the extension removed. By default output files will be overwritten.
196Use - as the only file name to read from stdin and write to stdout.
197
198Wildcards are accepted: testdir/*.txt will compress all files in testdir ending with .txt
199Directories can be wildcards as well. testdir/*/*.txt will match testdir/subdir/b.txt
200
201File names beginning with 'http://' and 'https://' will be downloaded and decompressed.
202Extensions on downloaded files are ignored. Only http response code 200 is accepted.
203
204Options:
205  -bench int
206    	Run benchmark n times. No output will be written
207  -c	Write all output to stdout. Multiple input files will be concatenated
208  -help
209    	Display help
210  -q	Don't write any output to terminal, except errors
211  -rm
212    	Delete source file(s) after successful decompression
213  -safe
214    	Do not overwrite output files
215  -verify
216    	Verify files, but do not write output
217```
218
219## s2sx: self-extracting archives
220
221s2sx allows creating self-extracting archives with no dependencies.
222
223By default, executables are created for the same platforms as the host os,
224but this can be overridden with `-os` and `-arch` parameters.
225
226Extracted files have 0666 permissions, except when untar option used.
227
228```
229Usage: s2sx [options] file1 file2
230
231Compresses all files supplied as input separately.
232If files have '.s2' extension they are assumed to be compressed already.
233Output files are written as 'filename.s2sx' and with '.exe' for windows targets.
234If output is big, an additional file with ".more" is written. This must be included as well.
235By default output files will be overwritten.
236
237Wildcards are accepted: testdir/*.txt will compress all files in testdir ending with .txt
238Directories can be wildcards as well. testdir/*/*.txt will match testdir/subdir/b.txt
239
240Options:
241  -arch string
242        Destination architecture (default "amd64")
243  -c    Write all output to stdout. Multiple input files will be concatenated
244  -cpu int
245        Compress using this amount of threads (default 32)
246  -help
247        Display help
248  -max string
249        Maximum executable size. Rest will be written to another file. (default "1G")
250  -os string
251        Destination operating system (default "windows")
252  -q    Don't write any output to terminal, except errors
253  -rm
254        Delete source file(s) after successful compression
255  -safe
256        Do not overwrite output files
257  -untar
258        Untar on destination
259```
260
261Available platforms are:
262
263 * darwin-amd64
264 * darwin-arm64
265 * linux-amd64
266 * linux-arm
267 * linux-arm64
268 * linux-mips64
269 * linux-ppc64le
270 * windows-386
271 * windows-amd64
272
273By default, there is a size limit of 1GB for the output executable.
274
275When this is exceeded the remaining file content is written to a file called
276output+`.more`. This file must be included for a successful extraction and
277placed alongside the executable for a successful extraction.
278
279This file *must* have the same name as the executable, so if the executable is renamed,
280so must the `.more` file.
281
282This functionality is disabled with stdin/stdout.
283
284### Self-extracting TAR files
285
286If you wrap a TAR file you can specify `-untar` to make it untar on the destination host.
287
288Files are extracted to the current folder with the path specified in the tar file.
289
290Note that tar files are not validated before they are wrapped.
291
292For security reasons files that move below the root folder are not allowed.
293
294# Performance
295
296This section will focus on comparisons to Snappy.
297This package is solely aimed at replacing Snappy as a high speed compression package.
298If you are mainly looking for better compression [zstandard](https://github.com/klauspost/compress/tree/master/zstd#zstd)
299gives better compression, but typically at speeds slightly below "better" mode in this package.
300
301Compression is increased compared to Snappy, mostly around 5-20% and the throughput is typically 25-40% increased (single threaded) compared to the Snappy Go implementation.
302
303Streams are concurrently compressed. The stream will be distributed among all available CPU cores for the best possible throughput.
304
305A "better" compression mode is also available. This allows to trade a bit of speed for a minor compression gain.
306The content compressed in this mode is fully compatible with the standard decoder.
307
308Snappy vs S2 **compression** speed on 16 core (32 thread) computer, using all threads and a single thread (1 CPU):
309
310| File                                                                                                | S2 speed | S2 Throughput | S2 % smaller | S2 "better" | "better" throughput | "better" % smaller |
311|-----------------------------------------------------------------------------------------------------|----------|---------------|--------------|-------------|---------------------|--------------------|
312| [rawstudio-mint14.tar](https://files.klauspost.com/compress/rawstudio-mint14.7z)                    | 12.70x   | 10556 MB/s    | 7.35%        | 4.15x       | 3455 MB/s           | 12.79%             |
313| (1 CPU)                                                                                             | 1.14x    | 948 MB/s      | -            | 0.42x       | 349 MB/s            | -                  |
314| [github-june-2days-2019.json](https://files.klauspost.com/compress/github-june-2days-2019.json.zst) | 17.13x   | 14484 MB/s    | 31.60%       | 10.09x      | 8533 MB/s           | 37.71%             |
315| (1 CPU)                                                                                             | 1.33x    | 1127 MB/s     | -            | 0.70x       | 589 MB/s            | -                  |
316| [github-ranks-backup.bin](https://files.klauspost.com/compress/github-ranks-backup.bin.zst)         | 15.14x   | 12000 MB/s    | -5.79%       | 6.59x       | 5223 MB/s           | 5.80%              |
317| (1 CPU)                                                                                             | 1.11x    | 877 MB/s      | -            | 0.47x       | 370 MB/s            | -                  |
318| [consensus.db.10gb](https://files.klauspost.com/compress/consensus.db.10gb.zst)                     | 14.62x   | 12116 MB/s    | 15.90%       | 5.35x       | 4430 MB/s           | 16.08%             |
319| (1 CPU)                                                                                             | 1.38x    | 1146 MB/s     | -            | 0.38x       | 312 MB/s            | -                  |
320| [adresser.json](https://files.klauspost.com/compress/adresser.json.zst)                             | 8.83x    | 17579 MB/s    | 43.86%       | 6.54x       | 13011 MB/s          | 47.23%             |
321| (1 CPU)                                                                                             | 1.14x    | 2259 MB/s     | -            | 0.74x       | 1475 MB/s           | -                  |
322| [gob-stream](https://files.klauspost.com/compress/gob-stream.7z)                                    | 16.72x   | 14019 MB/s    | 24.02%       | 10.11x      | 8477 MB/s           | 30.48%             |
323| (1 CPU)                                                                                             | 1.24x    | 1043 MB/s     | -            | 0.70x       | 586 MB/s            | -                  |
324| [10gb.tar](http://mattmahoney.net/dc/10gb.html)                                                     | 13.33x   | 9254 MB/s     | 1.84%        | 6.75x       | 4686 MB/s           | 6.72%              |
325| (1 CPU)                                                                                             | 0.97x    | 672 MB/s      | -            | 0.53x       | 366 MB/s            | -                  |
326| sharnd.out.2gb                                                                                      | 2.11x    | 12639 MB/s    | 0.01%        | 1.98x       | 11833 MB/s          | 0.01%              |
327| (1 CPU)                                                                                             | 0.93x    | 5594 MB/s     | -            | 1.34x       | 8030 MB/s           | -                  |
328| [enwik9](http://mattmahoney.net/dc/textdata.html)                                                   | 19.34x   | 8220 MB/s     | 3.98%        | 7.87x       | 3345 MB/s           | 15.82%             |
329| (1 CPU)                                                                                             | 1.06x    | 452 MB/s      | -            | 0.50x       | 213 MB/s            | -                  |
330| [silesia.tar](http://sun.aei.polsl.pl/~sdeor/corpus/silesia.zip)                                    | 10.48x   | 6124 MB/s     | 5.67%        | 3.76x       | 2197 MB/s           | 12.60%             |
331| (1 CPU)                                                                                             | 0.97x    | 568 MB/s      | -            | 0.46x       | 271 MB/s            | -                  |
332| [enwik10](https://encode.su/threads/3315-enwik10-benchmark-results)                                 | 21.07x   | 9020 MB/s     | 6.36%        | 6.91x       | 2959 MB/s           | 16.95%             |
333| (1 CPU)                                                                                             | 1.07x    | 460 MB/s      | -            | 0.51x       | 220 MB/s            | -                  |
334
335### Legend
336
337* `S2 speed`: Speed of S2 compared to Snappy, using 16 cores and 1 core.
338* `S2 throughput`: Throughput of S2 in MB/s.
339* `S2 % smaller`: How many percent of the Snappy output size is S2 better.
340* `S2 "better"`: Speed when enabling "better" compression mode in S2 compared to Snappy.
341* `"better" throughput`: Speed when enabling "better" compression mode in S2 compared to Snappy.
342* `"better" % smaller`: How many percent of the Snappy output size is S2 better when using "better" compression.
343
344There is a good speedup across the board when using a single thread and a significant speedup when using multiple threads.
345
346Machine generated data gets by far the biggest compression boost, with size being being reduced by up to 45% of Snappy size.
347
348The "better" compression mode sees a good improvement in all cases, but usually at a performance cost.
349
350Incompressible content (`sharnd.out.2gb`, 2GB random data) sees the smallest speedup.
351This is likely dominated by synchronization overhead, which is confirmed by the fact that single threaded performance is higher (see above).
352
353## Decompression
354
355S2 attempts to create content that is also fast to decompress, except in "better" mode where the smallest representation is used.
356
357S2 vs Snappy **decompression** speed. Both operating on single core:
358
359| File                                                                                                | S2 Throughput | vs. Snappy | Better Throughput | vs. Snappy |
360|-----------------------------------------------------------------------------------------------------|---------------|------------|-------------------|------------|
361| [rawstudio-mint14.tar](https://files.klauspost.com/compress/rawstudio-mint14.7z)                    | 2117 MB/s     | 1.14x      | 1738 MB/s         | 0.94x      |
362| [github-june-2days-2019.json](https://files.klauspost.com/compress/github-june-2days-2019.json.zst) | 2401 MB/s     | 1.25x      | 2307 MB/s         | 1.20x      |
363| [github-ranks-backup.bin](https://files.klauspost.com/compress/github-ranks-backup.bin.zst)         | 2075 MB/s     | 0.98x      | 1764 MB/s         | 0.83x      |
364| [consensus.db.10gb](https://files.klauspost.com/compress/consensus.db.10gb.zst)                     | 2967 MB/s     | 1.05x      | 2885 MB/s         | 1.02x      |
365| [adresser.json](https://files.klauspost.com/compress/adresser.json.zst)                             | 4141 MB/s     | 1.07x      | 4184 MB/s         | 1.08x      |
366| [gob-stream](https://files.klauspost.com/compress/gob-stream.7z)                                    | 2264 MB/s     | 1.12x      | 2185 MB/s         | 1.08x      |
367| [10gb.tar](http://mattmahoney.net/dc/10gb.html)                                                     | 1525 MB/s     | 1.03x      | 1347 MB/s         | 0.91x      |
368| sharnd.out.2gb                                                                                      | 3813 MB/s     | 0.79x      | 3900 MB/s         | 0.81x      |
369| [enwik9](http://mattmahoney.net/dc/textdata.html)                                                   | 1246 MB/s     | 1.29x      | 967 MB/s          | 1.00x      |
370| [silesia.tar](http://sun.aei.polsl.pl/~sdeor/corpus/silesia.zip)                                    | 1433 MB/s     | 1.12x      | 1203 MB/s         | 0.94x      |
371| [enwik10](https://encode.su/threads/3315-enwik10-benchmark-results)                                 | 1284 MB/s     | 1.32x      | 1010 MB/s         | 1.04x      |
372
373### Legend
374
375* `S2 Throughput`: Decompression speed of S2 encoded content.
376* `Better Throughput`: Decompression speed of S2 "better" encoded content.
377* `vs Snappy`: Decompression speed of S2 "better" mode compared to Snappy and absolute speed.
378
379
380While the decompression code hasn't changed, there is a significant speedup in decompression speed.
381S2 prefers longer matches and will typically only find matches that are 6 bytes or longer.
382While this reduces compression a bit, it improves decompression speed.
383
384The "better" compression mode will actively look for shorter matches, which is why it has a decompression speed quite similar to Snappy.
385
386Without assembly decompression is also very fast; single goroutine decompression speed. No assembly:
387
388| File                           | S2 Throughput | S2 throughput |
389|--------------------------------|--------------|---------------|
390| consensus.db.10gb.s2           | 1.84x        | 2289.8 MB/s   |
391| 10gb.tar.s2                    | 1.30x        | 867.07 MB/s   |
392| rawstudio-mint14.tar.s2        | 1.66x        | 1329.65 MB/s  |
393| github-june-2days-2019.json.s2 | 2.36x        | 1831.59 MB/s  |
394| github-ranks-backup.bin.s2     | 1.73x        | 1390.7 MB/s   |
395| enwik9.s2                      | 1.67x        | 681.53 MB/s   |
396| adresser.json.s2               | 3.41x        | 4230.53 MB/s  |
397| silesia.tar.s2                 | 1.52x        | 811.58        |
398
399Even though S2 typically compresses better than Snappy, decompression speed is always better.
400
401## Block compression
402
403
404When compressing blocks no concurrent compression is performed just as Snappy.
405This is because blocks are for smaller payloads and generally will not benefit from concurrent compression.
406
407An important change is that incompressible blocks will not be more than at most 10 bytes bigger than the input.
408In rare, worst case scenario Snappy blocks could be significantly bigger than the input.
409
410### Mixed content blocks
411
412The most reliable is a wide dataset.
413For this we use `webdevdata.org-2015-01-07-subset`, 53927 files, total input size: 4,014,526,923 bytes.
414Single goroutine used.
415
416| *                 | Input      | Output     | Reduction | MB/s   |
417|-------------------|------------|------------|-----------|--------|
418| S2                | 4014526923 | 1062282489 | 73.54%    | **861.44** |
419| S2 Better         | 4014526923 | 981221284  | **75.56%** | 399.54 |
420| Snappy            | 4014526923 | 1128667736 | 71.89%    | 741.29 |
421| S2, Snappy Output | 4014526923 | 1093784815 | 72.75%    | 843.66 |
422
423S2 delivers both the best single threaded throuhput with regular mode and the best compression rate with "better" mode.
424
425When outputting Snappy compatible output it still delivers better throughput (100MB/s more) and better compression.
426
427As can be seen from the other benchmarks decompression should also be easier on the S2 generated output.
428
429### Standard block compression
430
431Benchmarking single block performance is subject to a lot more variation since it only tests a limited number of file patterns.
432So individual benchmarks should only be seen as a guideline and the overall picture is more important.
433
434These micro-benchmarks are with data in cache and trained branch predictors. For a more realistic benchmark see the mixed content above.
435
436Block compression. Parallel benchmark running on 16 cores, 16 goroutines.
437
438AMD64 assembly is use for both S2 and Snappy.
439
440| Absolute Perf         | Snappy size | S2 Size | Snappy Speed | S2 Speed    | Snappy dec  | S2 dec      |
441|-----------------------|-------------|---------|--------------|-------------|-------------|-------------|
442| html                  | 22843       | 21111   | 16246 MB/s   | 17438 MB/s  | 40972 MB/s  | 49263 MB/s  |
443| urls.10K              | 335492      | 287326  | 7943 MB/s    | 9693 MB/s   | 22523 MB/s  | 26484 MB/s  |
444| fireworks.jpeg        | 123034      | 123100  | 349544 MB/s  | 273889 MB/s | 718321 MB/s | 827552 MB/s |
445| fireworks.jpeg (200B) | 146         | 155     | 8869 MB/s    | 17773 MB/s  | 33691 MB/s  | 52421 MB/s  |
446| paper-100k.pdf        | 85304       | 84459   | 167546 MB/s  | 101263 MB/s | 326905 MB/s | 291944 MB/s |
447| html_x_4              | 92234       | 21113   | 15194 MB/s   | 50670 MB/s  | 30843 MB/s  | 32217 MB/s  |
448| alice29.txt           | 88034       | 85975   | 5936 MB/s    | 6139 MB/s   | 12882 MB/s  | 20044 MB/s  |
449| asyoulik.txt          | 77503       | 79650   | 5517 MB/s    | 6366 MB/s   | 12735 MB/s  | 22806 MB/s  |
450| lcet10.txt            | 234661      | 220670  | 6235 MB/s    | 6067 MB/s   | 14519 MB/s  | 18697 MB/s  |
451| plrabn12.txt          | 319267      | 317985  | 5159 MB/s    | 5726 MB/s   | 11923 MB/s  | 19901 MB/s  |
452| geo.protodata         | 23335       | 18690   | 21220 MB/s   | 26529 MB/s  | 56271 MB/s  | 62540 MB/s  |
453| kppkn.gtb             | 69526       | 65312   | 9732 MB/s    | 8559 MB/s   | 18491 MB/s  | 18969 MB/s  |
454| alice29.txt (128B)    | 80          | 82      | 6691 MB/s    | 15489 MB/s  | 31883 MB/s  | 38874 MB/s  |
455| alice29.txt (1000B)   | 774         | 774     | 12204 MB/s   | 13000 MB/s  | 48056 MB/s  | 52341 MB/s  |
456| alice29.txt (10000B)  | 6648        | 6933    | 10044 MB/s   | 12806 MB/s  | 32378 MB/s  | 46322 MB/s  |
457| alice29.txt (20000B)  | 12686       | 13574   | 7733 MB/s    | 11210 MB/s  | 30566 MB/s  | 58969 MB/s  |
458
459
460| Relative Perf         | Snappy size | S2 size improved | S2 Speed | S2 Dec Speed |
461|-----------------------|-------------|------------------|----------|--------------|
462| html                  | 22.31%      | 7.58%            | 1.07x    | 1.20x        |
463| urls.10K              | 47.78%      | 14.36%           | 1.22x    | 1.18x        |
464| fireworks.jpeg        | 99.95%      | -0.05%           | 0.78x    | 1.15x        |
465| fireworks.jpeg (200B) | 73.00%      | -6.16%           | 2.00x    | 1.56x        |
466| paper-100k.pdf        | 83.30%      | 0.99%            | 0.60x    | 0.89x        |
467| html_x_4              | 22.52%      | 77.11%           | 3.33x    | 1.04x        |
468| alice29.txt           | 57.88%      | 2.34%            | 1.03x    | 1.56x        |
469| asyoulik.txt          | 61.91%      | -2.77%           | 1.15x    | 1.79x        |
470| lcet10.txt            | 54.99%      | 5.96%            | 0.97x    | 1.29x        |
471| plrabn12.txt          | 66.26%      | 0.40%            | 1.11x    | 1.67x        |
472| geo.protodata         | 19.68%      | 19.91%           | 1.25x    | 1.11x        |
473| kppkn.gtb             | 37.72%      | 6.06%            | 0.88x    | 1.03x        |
474| alice29.txt (128B)    | 62.50%      | -2.50%           | 2.31x    | 1.22x        |
475| alice29.txt (1000B)   | 77.40%      | 0.00%            | 1.07x    | 1.09x        |
476| alice29.txt (10000B)  | 66.48%      | -4.29%           | 1.27x    | 1.43x        |
477| alice29.txt (20000B)  | 63.43%      | -7.00%           | 1.45x    | 1.93x        |
478
479Speed is generally at or above Snappy. Small blocks gets a significant speedup, although at the expense of size.
480
481Decompression speed is better than Snappy, except in one case.
482
483Since payloads are very small the variance in terms of size is rather big, so they should only be seen as a general guideline.
484
485Size is on average around Snappy, but varies on content type.
486In cases where compression is worse, it usually is compensated by a speed boost.
487
488
489### Better compression
490
491Benchmarking single block performance is subject to a lot more variation since it only tests a limited number of file patterns.
492So individual benchmarks should only be seen as a guideline and the overall picture is more important.
493
494| Absolute Perf         | Snappy size | Better Size | Snappy Speed | Better Speed | Snappy dec  | Better dec  |
495|-----------------------|-------------|-------------|--------------|--------------|-------------|-------------|
496| html                  | 22843       | 19833       | 16246 MB/s   | 7731 MB/s    | 40972 MB/s  | 40292 MB/s  |
497| urls.10K              | 335492      | 253529      | 7943 MB/s    | 3980 MB/s    | 22523 MB/s  | 20981 MB/s  |
498| fireworks.jpeg        | 123034      | 123100      | 349544 MB/s  | 9760 MB/s    | 718321 MB/s | 823698 MB/s |
499| fireworks.jpeg (200B) | 146         | 142         | 8869 MB/s    | 594 MB/s     | 33691 MB/s  | 30101 MB/s  |
500| paper-100k.pdf        | 85304       | 82915       | 167546 MB/s  | 7470 MB/s    | 326905 MB/s | 198869 MB/s |
501| html_x_4              | 92234       | 19841       | 15194 MB/s   | 23403 MB/s   | 30843 MB/s  | 30937 MB/s  |
502| alice29.txt           | 88034       | 73218       | 5936 MB/s    | 2945 MB/s    | 12882 MB/s  | 16611 MB/s  |
503| asyoulik.txt          | 77503       | 66844       | 5517 MB/s    | 2739 MB/s    | 12735 MB/s  | 14975 MB/s  |
504| lcet10.txt            | 234661      | 190589      | 6235 MB/s    | 3099 MB/s    | 14519 MB/s  | 16634 MB/s  |
505| plrabn12.txt          | 319267      | 270828      | 5159 MB/s    | 2600 MB/s    | 11923 MB/s  | 13382 MB/s  |
506| geo.protodata         | 23335       | 18278       | 21220 MB/s   | 11208 MB/s   | 56271 MB/s  | 57961 MB/s  |
507| kppkn.gtb             | 69526       | 61851       | 9732 MB/s    | 4556 MB/s    | 18491 MB/s  | 16524 MB/s  |
508| alice29.txt (128B)    | 80          | 81          | 6691 MB/s    | 529 MB/s     | 31883 MB/s  | 34225 MB/s  |
509| alice29.txt (1000B)   | 774         | 748         | 12204 MB/s   | 1943 MB/s    | 48056 MB/s  | 42068 MB/s  |
510| alice29.txt (10000B)  | 6648        | 6234        | 10044 MB/s   | 2949 MB/s    | 32378 MB/s  | 28813 MB/s  |
511| alice29.txt (20000B)  | 12686       | 11584       | 7733 MB/s    | 2822 MB/s    | 30566 MB/s  | 27315 MB/s  |
512
513
514| Relative Perf         | Snappy size | Better size | Better Speed | Better dec |
515|-----------------------|-------------|-------------|--------------|------------|
516| html                  | 22.31%      | 13.18%      | 0.48x        | 0.98x      |
517| urls.10K              | 47.78%      | 24.43%      | 0.50x        | 0.93x      |
518| fireworks.jpeg        | 99.95%      | -0.05%      | 0.03x        | 1.15x      |
519| fireworks.jpeg (200B) | 73.00%      | 2.74%       | 0.07x        | 0.89x      |
520| paper-100k.pdf        | 83.30%      | 2.80%       | 0.07x        | 0.61x      |
521| html_x_4              | 22.52%      | 78.49%      | 0.04x        | 1.00x      |
522| alice29.txt           | 57.88%      | 16.83%      | 1.54x        | 1.29x      |
523| asyoulik.txt          | 61.91%      | 13.75%      | 0.50x        | 1.18x      |
524| lcet10.txt            | 54.99%      | 18.78%      | 0.50x        | 1.15x      |
525| plrabn12.txt          | 66.26%      | 15.17%      | 0.50x        | 1.12x      |
526| geo.protodata         | 19.68%      | 21.67%      | 0.50x        | 1.03x      |
527| kppkn.gtb             | 37.72%      | 11.04%      | 0.53x        | 0.89x      |
528| alice29.txt (128B)    | 62.50%      | -1.25%      | 0.47x        | 1.07x      |
529| alice29.txt (1000B)   | 77.40%      | 3.36%       | 0.08x        | 0.88x      |
530| alice29.txt (10000B)  | 66.48%      | 6.23%       | 0.16x        | 0.89x      |
531| alice29.txt (20000B)  | 63.43%      | 8.69%       | 0.29x        | 0.89x      |
532
533Except for the mostly incompressible JPEG image compression is better and usually in the
534double digits in terms of percentage reduction over Snappy.
535
536The PDF sample shows a significant slowdown compared to Snappy, as this mode tries harder
537to compress the data. Very small blocks are also not favorable for better compression, so throughput is way down.
538
539This mode aims to provide better compression at the expense of performance and achieves that
540without a huge performance penalty, except on very small blocks.
541
542Decompression speed suffers a little compared to the regular S2 mode,
543but still manages to be close to Snappy in spite of increased compression.
544
545# Best compression mode
546
547S2 offers a "best" compression mode.
548
549This will compress as much as possible with little regard to CPU usage.
550
551Mainly for offline compression, but where decompression speed should still
552be high and compatible with other S2 compressed data.
553
554Some examples compared on 16 core CPU, amd64 assembly used:
555
556```
557* enwik10
558Default... 10000000000 -> 4761467548 [47.61%]; 1.098s, 8685.6MB/s
559Better...  10000000000 -> 4219438251 [42.19%]; 1.925s, 4954.2MB/s
560Best...    10000000000 -> 3627364337 [36.27%]; 43.051s, 221.5MB/s
561
562* github-june-2days-2019.json
563Default... 6273951764 -> 1043196283 [16.63%]; 431ms, 13882.3MB/s
564Better...  6273951764 -> 949146808 [15.13%]; 547ms, 10938.4MB/s
565Best...    6273951764 -> 832855506 [13.27%]; 9.455s, 632.8MB/s
566
567* nyc-taxi-data-10M.csv
568Default... 3325605752 -> 1095998837 [32.96%]; 324ms, 9788.7MB/s
569Better...  3325605752 -> 954776589 [28.71%]; 491ms, 6459.4MB/s
570Best...    3325605752 -> 779098746 [23.43%]; 8.29s, 382.6MB/s
571
572* 10gb.tar
573Default... 10065157632 -> 5916578242 [58.78%]; 1.028s, 9337.4MB/s
574Better...  10065157632 -> 5649207485 [56.13%]; 1.597s, 6010.6MB/s
575Best...    10065157632 -> 5208719802 [51.75%]; 32.78s, 292.8MB/
576
577* consensus.db.10gb
578Default... 10737418240 -> 4562648848 [42.49%]; 882ms, 11610.0MB/s
579Better...  10737418240 -> 4542428129 [42.30%]; 1.533s, 6679.7MB/s
580Best...    10737418240 -> 4244773384 [39.53%]; 42.96s, 238.4MB/s
581```
582
583Decompression speed should be around the same as using the 'better' compression mode.
584
585# Concatenating blocks and streams.
586
587Concatenating streams will concatenate the output of both without recompressing them.
588While this is inefficient in terms of compression it might be usable in certain scenarios.
589The 10 byte 'stream identifier' of the second stream can optionally be stripped, but it is not a requirement.
590
591Blocks can be concatenated using the `ConcatBlocks` function.
592
593Snappy blocks/streams can safely be concatenated with S2 blocks and streams.
594
595# Format Extensions
596
597* Frame [Stream identifier](https://github.com/google/snappy/blob/master/framing_format.txt#L68) changed from `sNaPpY` to `S2sTwO`.
598* [Framed compressed blocks](https://github.com/google/snappy/blob/master/format_description.txt) can be up to 4MB (up from 64KB).
599* Compressed blocks can have an offset of `0`, which indicates to repeat the last seen offset.
600
601Repeat offsets must be encoded as a [2.2.1. Copy with 1-byte offset (01)](https://github.com/google/snappy/blob/master/format_description.txt#L89), where the offset is 0.
602
603The length is specified by reading the 3-bit length specified in the tag and decode using this table:
604
605| Length | Actual Length        |
606|--------|----------------------|
607| 0      | 4                    |
608| 1      | 5                    |
609| 2      | 6                    |
610| 3      | 7                    |
611| 4      | 8                    |
612| 5      | 8 + read 1 byte      |
613| 6      | 260 + read 2 bytes   |
614| 7      | 65540 + read 3 bytes |
615
616This allows any repeat offset + length to be represented by 2 to 5 bytes.
617
618Lengths are stored as little endian values.
619
620The first copy of a block cannot be a repeat offset and the offset is not carried across blocks in streams.
621
622Default streaming block size is 1MB.
623
624# LICENSE
625
626This code is based on the [Snappy-Go](https://github.com/golang/snappy) implementation.
627
628Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
629