Giter Site home page Giter Site logo

libdeflate's Introduction

Overview

libdeflate is a library for fast, whole-buffer DEFLATE-based compression and decompression.

The supported formats are:

  • DEFLATE (raw)
  • zlib (a.k.a. DEFLATE with a zlib wrapper)
  • gzip (a.k.a. DEFLATE with a gzip wrapper)

libdeflate is heavily optimized. It is significantly faster than the zlib library, both for compression and decompression, and especially on x86 and ARM processors. In addition, libdeflate provides optional high compression modes that provide a better compression ratio than the zlib's "level 9".

libdeflate itself is a library. The following command-line programs which use this library are also included:

  • libdeflate-gzip, a program which can be a drop-in replacement for standard gzip under some circumstances. Note that libdeflate-gzip has some limitations; it is provided for convenience and is not meant to be the main use case of libdeflate. It needs a lot of memory to process large files, and it omits support for some infrequently-used options of GNU gzip.

  • benchmark, a test program that does round-trip compression and decompression of the provided data, and measures the compression and decompression speed. It can use libdeflate, zlib, or a combination of the two.

  • checksum, a test program that checksums the provided data with Adler-32 or CRC-32, and optionally measures the speed. It can use libdeflate or zlib.

For the release notes, see the NEWS file.

Table of Contents

Building

Using CMake

libdeflate uses CMake. It can be built just like any other CMake project, e.g. with:

cmake -B build && cmake --build build

By default the following targets are built:

  • The static library (normally called libdeflate.a)
  • The shared library (normally called libdeflate.so)
  • The libdeflate-gzip program, including its alias libdeflate-gunzip

Besides the standard CMake build and installation options, there are some libdeflate-specific build options. See CMakeLists.txt for the list of these options. To set an option, add -DOPTION=VALUE to the cmake command.

Prebuilt Windows binaries can be downloaded from https://github.com/ebiggers/libdeflate/releases.

Directly integrating the library sources

Although the official build system is CMake, care has been taken to keep the library source files compilable directly, without a prerequisite configuration step. Therefore, it is also fine to just add the library source files directly to your application, without using CMake.

You should compile both lib/*.c and lib/*/*.c. You don't need to worry about excluding irrelevant architecture-specific code, as this is already handled in the source files themselves using #ifdefs.

If you are doing a freestanding build with -ffreestanding, you must add -DFREESTANDING as well (matching what the CMakeLists.txt does).

Supported compilers

  • gcc: v4.9 and later
  • clang: v3.9 and later (upstream), Xcode 8 and later (Apple)
  • MSVC: Visual Studio 2015 and later
  • Other compilers: any other C99-compatible compiler should work, though if your compiler pretends to be gcc, clang, or MSVC, it needs to be sufficiently compatible with the compiler it pretends to be.

The above are the minimums, but using a newer compiler allows more of the architecture-optimized code to be built. libdeflate is most heavily optimized for gcc and clang, but MSVC is supported fairly well now too.

The recommended optimization flag is -O2, and the CMakeLists.txt sets this for release builds. -O3 is fine too, but often -O2 actually gives better results. It's unnecessary to add flags such as -mavx2 or /arch:AVX2, though you can do so if you want to. Most of the relevant optimized functions are built regardless of such flags, and appropriate ones are selected at runtime.

API

libdeflate has a simple API that is not zlib-compatible. You can create compressors and decompressors and use them to compress or decompress buffers. See libdeflate.h for details.

There is currently no support for streaming. This has been considered, but it always significantly increases complexity and slows down fast paths. Unfortunately, at this point it remains a future TODO. So: if your application compresses data in "chunks", say, less than 1 MB in size, then libdeflate is a great choice for you; that's what it's designed to do. This is perfect for certain use cases such as transparent filesystem compression. But if your application compresses large files as a single compressed stream, similarly to the gzip program, then libdeflate isn't for you.

Note that with chunk-based compression, you generally should have the uncompressed size of each chunk stored outside of the compressed data itself. This enables you to allocate an output buffer of the correct size without guessing. However, libdeflate's decompression routines do optionally provide the actual number of output bytes in case you need it.

Windows developers: note that the calling convention of libdeflate.dll is "cdecl". (libdeflate v1.4 through v1.12 used "stdcall" instead.)

Bindings for other programming languages

The libdeflate project itself only provides a C library. If you need to use libdeflate from a programming language other than C or C++, consider using the following bindings:

Note: these are third-party projects which haven't necessarily been vetted by the authors of libdeflate. Please direct all questions, bugs, and improvements for these bindings to their authors.

Also, unfortunately many of these bindings bundle or pin an old version of libdeflate. To avoid known issues in old versions and to improve performance, before using any of these bindings please ensure that the bundled or pinned version of libdeflate has been upgraded to the latest release.

DEFLATE vs. zlib vs. gzip

The DEFLATE format (rfc1951), the zlib format (rfc1950), and the gzip format (rfc1952) are commonly confused with each other as well as with the zlib software library, which actually supports all three formats. libdeflate (this library) also supports all three formats.

Briefly, DEFLATE is a raw compressed stream, whereas zlib and gzip are different wrappers for this stream. Both zlib and gzip include checksums, but gzip can include extra information such as the original filename. Generally, you should choose a format as follows:

  • If you are compressing whole files with no subdivisions, similar to the gzip program, you probably should use the gzip format.
  • Otherwise, if you don't need the features of the gzip header and footer but do still want a checksum for corruption detection, you probably should use the zlib format.
  • Otherwise, you probably should use raw DEFLATE. This is ideal if you don't need checksums, e.g. because they're simply not needed for your use case or because you already compute your own checksums that are stored separately from the compressed stream.

Note that gzip and zlib streams can be distinguished from each other based on their starting bytes, but this is not necessarily true of raw DEFLATE streams.

Compression levels

An often-underappreciated fact of compression formats such as DEFLATE is that there are an enormous number of different ways that a given input could be compressed. Different algorithms and different amounts of computation time will result in different compression ratios, while remaining equally compatible with the decompressor.

For this reason, the commonly used zlib library provides nine compression levels. Level 1 is the fastest but provides the worst compression; level 9 provides the best compression but is the slowest. It defaults to level 6. libdeflate uses this same design but is designed to improve on both zlib's performance and compression ratio at every compression level. In addition, libdeflate's levels go up to 12 to make room for a minimum-cost-path based algorithm (sometimes called "optimal parsing") that can significantly improve on zlib's compression ratio.

If you are using DEFLATE (or zlib, or gzip) in your application, you should test different levels to see which works best for your application.

Motivation

Despite DEFLATE's widespread use mainly through the zlib library, in the compression community this format from the early 1990s is often considered obsolete. And in a few significant ways, it is.

So why implement DEFLATE at all, instead of focusing entirely on bzip2/LZMA/xz/LZ4/LZX/ZSTD/Brotli/LZHAM/LZFSE/[insert cool new format here]?

To do something better, you need to understand what came before. And it turns out that most ideas from DEFLATE are still relevant. Many of the newer formats share a similar structure as DEFLATE, with different tweaks. The effects of trivial but very useful tweaks, such as increasing the sliding window size, are often confused with the effects of nontrivial but less useful tweaks. And actually, many of these formats are similar enough that common algorithms and optimizations (e.g. those dealing with LZ77 matchfinding) can be reused.

In addition, comparing compressors fairly is difficult because the performance of a compressor depends heavily on optimizations which are not intrinsic to the compression format itself. In this respect, the zlib library sometimes compares poorly to certain newer code because zlib is not well optimized for modern processors. libdeflate addresses this by providing an optimized DEFLATE implementation which can be used for benchmarking purposes. And, of course, real applications can use it as well.

License

libdeflate is MIT-licensed.

I am not aware of any patents or patent applications relevant to libdeflate.

libdeflate's People

Contributors

4kills avatar antonblanchard avatar ap avatar astei avatar begasus avatar cielavenir avatar dankamongmen avatar djytw avatar dktapps avatar ebiggers avatar ferdnyc avatar ffontaine avatar gemesa avatar izumiraine avatar jzebedee avatar kiwiroy avatar kmilos avatar kylebarron avatar leleliu008 avatar michaelsbradleyjr avatar mmokrejs avatar orivej avatar pps83 avatar pyos avatar rouault avatar rreverser avatar seekingmeaning avatar shuffle2 avatar tansy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

libdeflate's Issues

Greater max_codeword_len?

Your library a very fast, even at level 12
Please implement lever upper to 12.
If I am no wrong, max_codeword_len=32 are safe for zip format and not increment the compress time too much.

Compress PNG

hi!
Tell me, whether it is possible to expect support of compression of PNG?

List of Wrappers in ReadMe

Hey @ebiggers,
first of all: I really appreciate your work with this amazing library that immensely speeds up (de)compression compared to standard zlib.

I've seen that some people on Github have created wrappers for this library for other programming languages (like these Rust bindings: https://github.com/adamkewley/libdeflater).
I wonder what you think about the suggestion to make a section in the ReadMe linking to such wrappers (like facebook has it with their zstd) in order to make it easier for people to use this great library with their language of choice!

To give my two cents: I've looked for a Go wrapper of this library (and maybe one exists already) but haven't found any, so I created one myself: https://github.com/4kills/go-libdeflate.

Edit: fixed link

test failure on ppc64el

On a recent build of the libdeflate 1.3 Debian package

SMOKEDATA=/<<PKGBUILDDIR>>/README.md WRAPPER= sh tools/exec_tests.sh
 ./test_checksums
 ./test_incomplete_codes
 ./test_slow_decompression
test_slow_decompression: Assertion failed: t < tz at programs/test_slow_decompression.c:446
Aborted

We've never run these particular tests before, so I don't know if this wasn't working in prior versions.

Full log is at https://buildd.debian.org/status/fetch.php?pkg=libdeflate&arch=ppc64el&ver=1.3-1&stamp=1566583337&file=log

Rename gzip application to deflate.

Dear ebiggers,

Thank you for your great work on redeeming the deflate algorithm and making a fast implementation. I have seen your work implemented as a library and seen its very impressive effects on speed.

Unfortunately, while I can install libdeflate via conda or via the debian package repo I cannot seem to find a command line application that implements libdeflate. Coming here at the source, I see that such a command line application is available, but unfortunately it is named gzip. The gzip application in libdeflate also does not support all the flag of the original gzip application and therefore has the potential to break scripts.

Most package maintainers are unwilling to create a package that overwrites the default gzip application with something that is not gzip.

Some other alternatives exist for gzip:

  • pigz (with -p 1) is faster on a single thread than gzip.
  • igzip (from intel's isa-l).

Note how these are not called gzip and are therefore easy to install and use alongside venerable gzip.

I think a renaming would alleviate this problem and allow libdeflate to be used much more often in everyday command line use.

I suggest using the name deflate. The name tells what it does, it stands out from gzip, and emphasises the connection to libdeflate. Also I was not able to find other applications that are already called deflate.

64 bit MSVC warnings

Warning 3   warning C4267: 'function' : conversion from 'size_t' to 'uint32_t', possible loss of data   F:\Data\alive\alive\3rdParty\libdeflate\common\common_defs.h    289
Warning 4   warning C4267: 'function' : conversion from 'size_t' to 'uint32_t', possible loss of data   F:\Data\alive\alive\3rdParty\libdeflate\common\common_defs.h    331
Warning 5   warning C4267: 'function' : conversion from 'size_t' to 'u32', possible loss of data    f:\data\alive\alive\3rdparty\libdeflate\lib\unaligned.h 159
Warning 1   warning C4244: 'return' : conversion from 'uint64_t' to 'unsigned int', possible loss of data   f:\data\alive\alive\3rdparty\libdeflate\common\compiler_msc.h   85
Warning 2   warning C4244: 'return' : conversion from 'uint64_t' to 'unsigned int', possible loss of data   f:\data\alive\alive\3rdparty\libdeflate\common\compiler_msc.h   93
Warning 6   warning C4018: '>=' : signed/unsigned mismatch  f:\data\alive\alive\3rdparty\libdeflate\lib\decompress_impl.h   277

Even when _M_X64 is defined

How about a paired web minifier?

Enhancement request/idea: Consider writing a minifier to pair with libdeflate, since a major use case of libdeflate is probably to compress web content – HTML, JS, and CSS files.

It might be possible to leverage libdeflate's parsing logic toward a web minifier's parser. Relatedly, if you knew that the input to the gzip compressor was minified HTML, CSS, and JS, could you accelerate the compression? Maybe the parser or match finder? Or, what if you knew that you weren't going to have any matches longer than say 40 bytes?

Some of this might be easier if you knew that the input wasn't just minified web content, but more specifically was content that you minified, according to your minifier rules, standards, or spec. So it would have certain features or patterns. Line endings would be normalized, there'd never be certain forms of whitespace in code areas, etc. We could even have metadata for these HTML, JS, and CSS files that reported the length of the file, the longest length repeated string, the max number of repeats, etc. Could that metadata significantly help libdeflate?

I'm not aware of a minifier written in C. It would probably be the fastest minifier on earth, by a wide margin, especially if you used the SIMD in parsing and matching that you use in libdeflate, and it would be an interesting and popular project on its own. I'm not good with C, but I could write a spec for the minifier and/or the minifier output. Some minifiers are unsafe and break websites, so it would be nice to have one that actually had a spec, and was safe.

Target attribute unsupported on lots of compilers

I just tried to pull the latest changes into Squash so I could enable AppVeyor (MSVC) builds for libdeflate, and it ended up triggering several issues on Travis. If you think it would be appropriate to ignore the warnings I could always pass -Wno-unknown-attributes, but it would probably be better to fix them…

I'm not sure what, exactly, is going on with OS X, but I think it's related. Those errors don't happen with 6e5ef3e.

Can a dev review my Rust bindings?

Hi,

I've been using libdeflate at work and I really like it. As a side-project--and to practice unsafe + FFI coding in Rust--I have implemented bindings to most of the libdeflate API but, if there's a dev around, could you review my design? I'm gradually getting closer to rolling it out publicly (it's on cargo, but I haven't put it on any social media sites etc.)

The benchmarks show that libdeflate does very well when compared with Rust's most popular compression library (flate2), but the corpus is mostly small files (favourable to libdeflate), I'm not comparing the compression ratio at this default setting, and I might be using flate2 sub-optimally, so take the numbers with a pinch of salt.

My main goal with the crate is to have a well-documented API so that developers can add libdeflate into their codebase easily, but also to not try and hide the API behind (e.g.) a streaming interface, so that developers know how the underlying protocol works (therefore making the decision to use libdeflate a deliberate one)

mkdir -p $LIBDIR $INCDIR

Dear @ebiggers, I am trying to use #46 (comment), but I get 2 errors:

install -Dm644 -t /soft/2/libdeflate-190703/lib libdeflate.a
install: failed to access '/soft/2/libdeflate-190703/lib': No such file or directory
make: *** [install] Error 1

and the same about include. It is because both lib and include directories do not exist and are not automatically created (bin is created automatically).
I suggest to add mkdir -p ... for both these directories:

install:all

Build fails on linux with error: unknown type name ‘__m256i’ in adler32

latest commit checkout ( 1286b4d )
Ubuntu 14.04 LTS
gcc 4.8.4

$ make
  CC       lib/aligned_malloc.o
  CC       lib/deflate_decompress.o
  CC       lib/x86_cpu_features.o
  CC       lib/deflate_compress.o
  CC       lib/adler32.o
In file included from lib/adler32.c:151:0:
lib/adler32_impl.h: In function ‘adler32_avx2’:
lib/adler32_impl.h:99:3: error: unknown type name ‘__m256i’
   const __m256i zeroes = _mm256_setzero_si256();
   ^
lib/adler32_impl.h:99:3: warning: implicit declaration of function ‘_mm256_setzero_si256’ [-Wimplicit-function-declaration]
lib/adler32_impl.h:100:3: error: unknown type name ‘__v32qi’
   const __v32qi multipliers = (__v32qi) { 32, 31, 30, 29, 28, 27, 26, 25,
   ^
lib/adler32_impl.h:100:32: error: ‘__v32qi’ undeclared (first use in this function)
   const __v32qi multipliers = (__v32qi) { 32, 31, 30, 29, 28, 27, 26, 25,
                                ^
lib/adler32_impl.h:100:32: note: each undeclared identifier is reported only once for each function it appears in
lib/adler32_impl.h:100:41: error: expected ‘,’ or ‘;’ before ‘{’ token
   const __v32qi multipliers = (__v32qi) { 32, 31, 30, 29, 28, 27, 26, 25,
                                         ^
lib/adler32_impl.h:104:3: error: unknown type name ‘__v16hi’
   const __v16hi ones = (__v16hi)_mm256_set1_epi16(1);
   ^
lib/adler32_impl.h:104:25: error: ‘__v16hi’ undeclared (first use in this function)
   const __v16hi ones = (__v16hi)_mm256_set1_epi16(1);
                         ^
lib/adler32_impl.h:104:33: error: expected ‘,’ or ‘;’ before ‘_mm256_set1_epi16’
   const __v16hi ones = (__v16hi)_mm256_set1_epi16(1);
                                 ^
lib/adler32_impl.h:104:3: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement]
   const __v16hi ones = (__v16hi)_mm256_set1_epi16(1);
   ^
lib/adler32_impl.h:105:3: error: unknown type name ‘__v8si’
   __v8si v_s1 = (__v8si)zeroes;
   ^
lib/adler32_impl.h:105:18: error: ‘__v8si’ undeclared (first use in this function)
   __v8si v_s1 = (__v8si)zeroes;
                  ^
lib/adler32_impl.h:105:25: error: expected ‘,’ or ‘;’ before ‘zeroes’
   __v8si v_s1 = (__v8si)zeroes;
                         ^
lib/adler32_impl.h:106:10: error: expected ‘;’ before ‘v_s1_sums’
   __v8si v_s1_sums = (__v8si)zeroes;
          ^
lib/adler32_impl.h:107:10: error: expected ‘;’ before ‘v_s2’
   __v8si v_s2 = (__v8si)zeroes;
          ^
lib/adler32_impl.h:110:4: error: unknown type name ‘__m256i’
    __m256i bytes = *(const __m256i *)p;
    ^
lib/adler32_impl.h:110:4: error: unknown type name ‘__m256i’
lib/adler32_impl.h:111:12: error: expected ‘;’ before ‘sums’
    __v16hi sums = (__v16hi)_mm256_maddubs_epi16(
            ^
lib/adler32_impl.h:113:4: error: ‘v_s1_sums’ undeclared (first use in this function)
    v_s1_sums += v_s1;
    ^
lib/adler32_impl.h:114:20: error: expected ‘;’ before ‘_mm256_sad_epu8’
    v_s1 += (__v8si)_mm256_sad_epu8(bytes, zeroes);
                    ^
lib/adler32_impl.h:115:4: error: ‘v_s2’ undeclared (first use in this function)
    v_s2 += (__v8si)_mm256_madd_epi16((__m256i)sums, (__m256i)ones);
    ^
lib/adler32_impl.h:115:20: error: expected ‘;’ before ‘_mm256_madd_epi16’
    v_s2 += (__v8si)_mm256_madd_epi16((__m256i)sums, (__m256i)ones);
                    ^
lib/adler32_impl.h:110:12: warning: unused variable ‘bytes’ [-Wunused-variable]
    __m256i bytes = *(const __m256i *)p;
            ^
lib/adler32_impl.h:118:18: error: expected ‘;’ before ‘_mm256_hadd_epi32’
   v_s1 = (__v8si)_mm256_hadd_epi32((__m256i)v_s1, zeroes);
                  ^
lib/adler32_impl.h:119:18: error: expected ‘;’ before ‘_mm256_hadd_epi32’
   v_s1 = (__v8si)_mm256_hadd_epi32((__m256i)v_s1, zeroes);
                  ^
lib/adler32_impl.h:120:13: error: subscripted value is neither array nor pointer nor vector
   s1 += v_s1[0] + v_s1[4];
             ^
lib/adler32_impl.h:120:23: error: subscripted value is neither array nor pointer nor vector
   s1 += v_s1[0] + v_s1[4];
                       ^
lib/adler32_impl.h:122:19: error: expected ‘;’ before ‘_mm256_slli_epi32’
   v_s2 += (__v8si)_mm256_slli_epi32((__m256i)v_s1_sums, 5);
                   ^
lib/adler32_impl.h:123:18: error: expected ‘;’ before ‘_mm256_hadd_epi32’
   v_s2 = (__v8si)_mm256_hadd_epi32((__m256i)v_s2, zeroes);
                  ^
lib/adler32_impl.h:124:18: error: expected ‘;’ before ‘_mm256_hadd_epi32’
   v_s2 = (__v8si)_mm256_hadd_epi32((__m256i)v_s2, zeroes);
                  ^
lib/adler32_impl.h:104:17: warning: unused variable ‘ones’ [-Wunused-variable]
   const __v16hi ones = (__v16hi)_mm256_set1_epi16(1);
                 ^
lib/adler32_impl.h:100:17: warning: unused variable ‘multipliers’ [-Wunused-variable]
   const __v32qi multipliers = (__v32qi) { 32, 31, 30, 29, 28, 27, 26, 25,
                 ^
lib/adler32_impl.h:99:17: warning: unused variable ‘zeroes’ [-Wunused-variable]
   const __m256i zeroes = _mm256_setzero_si256();
                 ^
make: *** [lib/adler32.o] Error 1

CMake

I'm trying to reduce build system duplication in Squash (see quixdb/squash#202 for the background). Would you be interested in a CMake-based system for libdeflate?

Coverity Scan

Hi Eric – How about putting libdeflate on Coverity Scan? It's free: https://scan.coverity.com/

Is there any downside? Maybe false positives? My impression is that Coverity is pretty good at controlling false positives, but I'm no expert.

Don't depend on undefined behavior

Unaligned access is undefined behavior, and not necessarily safe even with GCC on x86. For example, LZ4 had a problem recently with GCC 4.9 adding a new optimization which vectorized an operation, and the new instruction didn't support unaligned access (a lot of the vector extensions don't), which was causing crashes. wfLZ is still having a similar problem. http://fastcompression.blogspot.fr/2015/08/accessing-unaligned-memory.html has some interesting information.

Installation with --prefix

Hello!

Could you tell me, please, how to install libdeflate in a custom directory in the similar way as it is usually possible with ./configure --prefix "/my/custom/path"?
And what environmental variable I should export in this case?

Z_SYNC_FLUSH equivalent

Does libdeflate have some kind of equivalent to zlibs Z_SYNC_FLUSH?
For my application i need to compress a single packet of data completely, send it of, and then compress the next packet without resetting the compressor.

Does libdeflate_deflate_compress allways flush all the input data (if enough output space is available) or does is delay bits.

How about implementing PKZIP or zlib compatible?

Hi,

I've been looking for an alternative to zlib and have found libdeflate, but since the purpose is the deployment of the zip archive, I can not use your library as it is.

If you'd like to do that, if libdeflate supports compression and expansion of pkzip itself, or with an optional wrapper, it gets a far greater need than deflate-only support You can do it.

There is an implementation called minizip in zlib/contrib, which will be helpful compared with making it from scratch. Or just prepare an interface compatible with zlib. I will make programs using real with minizip so you do not need to prepare everything.

Thank you.

Writes corrupt files when compressed data > 4GB

Hi,

Just wanted to point out the gzip program produces truncated files for all writes that should be >4GB.

I imagine this should be a trivial fix (maybe define the file offset bits = 64, or fix some assumption of 32-bit file pointers?).

Ubuntu 18.04 WSL

How to set optimized options?

I am currently testing libdeflate to see if png decoding speeds up.

Although libdeflate_deflate_decompress_ex() on libdeflatestatic.lib is executed built using gcc-8 of msys2 in the Windows OS, the execution time is the same as compared with the inflate() of conventional zlib.

Is there an option to make it faster?

I examined the lib file, but there are symbols such as deflate_decompress_bmi.

The generate gzip executable fails on some gzip files while "normal" gzip happily decompresses them.

The used file are form the common crawl.

https://commoncrawl.s3.amazonaws.com/crawl-data/CC-MAIN-2017-39/segments/1505818685129.23/wet/CC-MAIN-20170919112242-20170919132242-00000.warc.wet.gz

The files seem to have a bad size descriptor at the end, but the program (and an implementation of the library) give and error about "Not enough space in the output buffer" value 3 I think.

And the generated gzip gives file corrupt or not in gzip format

While OS gzip and stuff like zlib (custom implementation or gzstream) WinRar and most other seem to work just fine.

Support for parallel processing

Do you plan to parallelize compression and decompression ?

Currently I am interested in decompression.

Decompress_template switches between UNCOMPRESSED and huffman code, but each will run on a separate thread. Each UNCOMPRESSED can be divided into further threads if certain conditions are satisfied.

In addition, c ++ 11 adds multithreading, so you do not need to consider the pthread problem.

Add support for custom allocators

In certain contexts, such as building the library for wasm32-unknown-unknown target or some embedded targets, it would be helpful if libdeflate allowed to provide own allocation callbacks, much like zlib does via options.

Alternatively, it appears that libdeflate always allocates same small fixed-size structures, so perhaps it could just use the stack for such temporary allocations instead?

ZIP format and libdeflate

I am looking for a way to increase the extraction speed on Android for a few files from 100's of ZIP files. I stumbled upon your library, which seems very optimized, but I am not sure if I could use it for my purpose. I currently use the reference minizip from the zlib library, but performance is way to slow.

Am I correct that your library doesn't support the zip format itself? Any tips for the way to use this for zip extraction?

Edit:
I did read the zip specification and it seems quite easy to parse it. I think that using libdeflate for a entry could be done. I will look into that.

ISO C99 doesn't support unnamed structs/unions

See quixdb/squash#199 for a bit of background. If you compile with GCC 4.4 in C99 mode it will result in an error; GNU99 mode works, but if you tell CMake that you want to use the C99 standard it will pass -std=c99 not -std=gnu99… regardless, apparently it's not valid C99 so it would probably be wise to change the code for portability reasons.

-Wpedantic should trigger the warning, assuming you're compiling in C99 mode. With GCC 4.4 (on CentOS 6), with -std=c99 (and no -Wpedantic), I get:

/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:170: warning: declaration does not declare anything
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:171: warning: declaration does not declare anything
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:357: warning: declaration does not declare anything
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:383: warning: declaration does not declare anything
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:385: warning: declaration does not declare anything
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c: In function ‘deflate_make_huffman_codes’:
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1113: error: ‘struct deflate_lens’ has no member named ‘litlen’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1119: error: ‘struct deflate_lens’ has no member named ‘offset’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c: In function ‘deflate_write_huffman_codes’:
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1320: error: ‘struct deflate_lens’ has no member named ‘litlen’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1326: error: ‘struct deflate_lens’ has no member named ‘offset’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1337: error: ‘struct deflate_lens’ has no member named ‘offset’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1341: error: ‘struct deflate_lens’ has no member named ‘all’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1342: error: ‘struct deflate_lens’ has no member named ‘all’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1343: error: ‘struct deflate_lens’ has no member named ‘all’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1347: error: ‘struct deflate_lens’ has no member named ‘all’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1352: error: ‘struct deflate_lens’ has no member named ‘all’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1353: error: ‘struct deflate_lens’ has no member named ‘all’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1354: error: ‘struct deflate_lens’ has no member named ‘all’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c: In function ‘deflate_write_sequences’:
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1381: error: ‘const struct deflate_lens’ has no member named ‘litlen’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1386: error: ‘const struct deflate_lens’ has no member named ‘litlen’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1391: error: ‘const struct deflate_lens’ has no member named ‘litlen’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1396: error: ‘const struct deflate_lens’ has no member named ‘litlen’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1403: error: ‘const struct deflate_lens’ has no member named ‘litlen’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1409: error: ‘const struct deflate_lens’ has no member named ‘litlen’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1415: error: ‘const struct deflate_lens’ has no member named ‘litlen’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1447: error: ‘const struct deflate_lens’ has no member named ‘litlen’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1464: error: ‘const struct deflate_lens’ has no member named ‘offset’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c: In function ‘deflate_write_end_of_block’:
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1486: error: ‘const struct deflate_lens’ has no member named ‘litlen’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c: In function ‘deflate_write_block’:
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1520: error: ‘struct deflate_compressor’ has no member named ‘sequences’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c: In function ‘deflate_compress_greedy’:
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1592: error: ‘struct deflate_compressor’ has no member named ‘sequences’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1607: error: ‘struct deflate_compressor’ has no member named ‘hc_mf’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1609: error: ‘struct deflate_compressor’ has no member named ‘hc_mf’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1623: error: ‘struct deflate_compressor’ has no member named ‘hc_mf’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1637: error: ‘struct deflate_compressor’ has no member named ‘hc_mf’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1656: error: ‘struct deflate_compressor’ has no member named ‘sequences’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c: In function ‘deflate_compress_lazy’:
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1689: error: ‘struct deflate_compressor’ has no member named ‘sequences’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1706: error: ‘struct deflate_compressor’ has no member named ‘hc_mf’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1708: error: ‘struct deflate_compressor’ has no member named ‘hc_mf’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1727: error: ‘struct deflate_compressor’ has no member named ‘hc_mf’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1752: error: ‘struct deflate_compressor’ has no member named ‘hc_mf’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1781: error: ‘struct deflate_compressor’ has no member named ‘hc_mf’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1804: error: ‘struct deflate_compressor’ has no member named ‘sequences’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1816: error: ‘struct deflate_compressor’ has no member named ‘hc_mf’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1834: error: ‘struct deflate_compressor’ has no member named ‘sequences’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c: In function ‘deflate_tally_item_list’:
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1862: error: ‘struct deflate_compressor’ has no member named ‘optimum’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c: In function ‘deflate_write_item_list’:
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1894: error: ‘struct deflate_compressor’ has no member named ‘optimum’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1906: error: ‘const struct deflate_lens’ has no member named ‘litlen’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1913: error: ‘const struct deflate_lens’ has no member named ‘litlen’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1928: error: ‘const struct deflate_lens’ has no member named ‘offset’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c: In function ‘deflate_set_costs’:
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1949: error: ‘const struct deflate_lens’ has no member named ‘litlen’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1949: error: ‘const struct deflate_lens’ has no member named ‘litlen’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1950: error: ‘struct deflate_compressor’ has no member named ‘costs’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1957: error: ‘const struct deflate_lens’ has no member named ‘litlen’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1957: error: ‘const struct deflate_lens’ has no member named ‘litlen’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1959: error: ‘struct deflate_compressor’ has no member named ‘costs’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1964: error: ‘const struct deflate_lens’ has no member named ‘offset’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1964: error: ‘const struct deflate_lens’ has no member named ‘offset’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:1966: error: ‘struct deflate_compressor’ has no member named ‘costs’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c: In function ‘deflate_set_default_costs’:
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:2011: error: ‘struct deflate_compressor’ has no member named ‘costs’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:2015: error: ‘struct deflate_compressor’ has no member named ‘costs’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:2020: error: ‘struct deflate_compressor’ has no member named ‘costs’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c: In function ‘deflate_adjust_costs’:
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:2045: error: ‘struct deflate_compressor’ has no member named ‘costs’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:2050: error: ‘struct deflate_compressor’ has no member named ‘costs’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:2056: error: ‘struct deflate_compressor’ has no member named ‘costs’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c: In function ‘deflate_optimize_and_write_block’:
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:2067: error: ‘struct deflate_compressor’ has no member named ‘optimum’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:2068: error: ‘struct deflate_compressor’ has no member named ‘num_optim_passes’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:2104: error: ‘struct deflate_compressor’ has no member named ‘costs’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:2133: error: ‘struct deflate_compressor’ has no member named ‘costs’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:2136: error: ‘struct deflate_compressor’ has no member named ‘costs’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:2148: error: ‘struct deflate_compressor’ has no member named ‘optimum’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c: In function ‘deflate_compress_near_optimal’:
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:2206: error: ‘struct deflate_compressor’ has no member named ‘bt_mf’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:2216: error: ‘struct deflate_compressor’ has no member named ‘cached_matches’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:2217: error: ‘struct deflate_compressor’ has no member named ‘cached_matches’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:2246: error: ‘struct deflate_compressor’ has no member named ‘bt_mf’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:2274: error: ‘struct deflate_compressor’ has no member named ‘bt_mf’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:2316: error: ‘struct deflate_compressor’ has no member named ‘bt_mf’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:2322: error: ‘struct deflate_compressor’ has no member named ‘bt_mf’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c: In function ‘deflate_alloc_compressor’:
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:2393: error: ‘struct deflate_compressor’ has no member named ‘optimal_end’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:2396: error: ‘struct deflate_compressor’ has no member named ‘nonoptimal_end’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:2445: error: ‘struct deflate_compressor’ has no member named ‘num_optim_passes’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:2451: error: ‘struct deflate_compressor’ has no member named ‘num_optim_passes’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:2457: error: ‘struct deflate_compressor’ has no member named ‘num_optim_passes’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:2463: error: ‘struct deflate_compressor’ has no member named ‘num_optim_passes’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:2469: error: ‘struct deflate_compressor’ has no member named ‘num_optim_passes’
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c: In function ‘deflate_compress’:
/home/nemequ/squash/plugins/libdeflate/libdeflate/src/deflate_compress.c:2506: error: ‘struct deflate_compressor’ has no member named ‘sequences’
make[2]: *** [plugins/libdeflate/CMakeFiles/squash0.8-plugin-libdeflate.dir/libdeflate/src/deflate_compress.c.o] Error 1
make[1]: *** [plugins/libdeflate/CMakeFiles/squash0.8-plugin-libdeflate.dir/all] Error 2
make: *** [all] Error 2

Slow gzip decompression on corrupted data

I was fuzz testing libdeflate (and haven't ran into any crashes), but I ran into a case where libdeflate_gzip_decompress() is running at under 4 MB/s (on corrupted data). I've uploaded the file in case you want to investigate. The test case, which takes 1.1 seconds to run on a 3984 byte input is:

int LLVMFuzzerTestOneInput(uint8_t const* buffer, size_t size) {
    size_t out_size = 2 * size;
    void* const out = malloc(out_size);
    size_t tmp;
    struct libdeflate_decompressor* dec = libdeflate_alloc_decompressor();
    for (size_t i = 0; i < 1000; ++i) {
      libdeflate_gzip_decompress(dec, buffer, size, out, out_size, &tmp);
    }
    libdeflate_free_decompressor(dec);
    free(out);
}

timeout-85b0de55cd04b2872c2eb1c013933ff9c0082581.gz

User control over minimum match length

One of the zlib features is the strategy option, which permits Z_DEFAULT_STRATEGY vs Z_FILTERED. The latter changes the minimum match length which correspondingly then favours huffman over LZ for small matches. On some data sets it can have a big impact.

The same logic can work for libdeflate. Eg with and without this tiny patch:

diff --git a/lib/deflate_compress.c b/lib/deflate_compress.c
index 9ecb8b6..5e7890a 100644
--- a/lib/deflate_compress.c
+++ b/lib/deflate_compress.c
@@ -2099,7 +2099,7 @@ deflate_compress_lazy(struct libdeflate_compressor * restrict c,
                                                               &cur_offset);
                        in_next += 1;
 
-                       if (cur_len < DEFLATE_MIN_MATCH_LEN) {
+                       if (cur_len < DEFLATE_MIN_MATCH_LEN+4) {
                                /* No match found.  Choose a literal.  */
                                deflate_choose_literal(c, *(in_next - 1), &litrunlen);
                                observe_literal(&c->split_stats, *(in_next - 1));
;#orig
@ gen1c[compress.../libdeflate]; ./gzip < /tmp/rn|wc -c
5544678
@ gen1c[compress.../libdeflate]; ./gzip -9 < /tmp/rn|wc -c
5352317

;# Patched
@ gen1c[compress.../libdeflate]; ./gzip < /tmp/rn|wc -c
5039812

;# Zlib
@ gen1c[compress.../libdeflate]; ~/work/compression/zlib_test Z_DEFAULT_STRATEGY < /tmp/rn|wc -c
5513639
@ gen1c[compress.../libdeflate]; ~/work/compression/zlib_test Z_FILTERED < /tmp/rn|wc -c
5118920
@ gen1c[compress.../libdeflate]; ~/work/compression/zlib_test Z_FILTERED 9 < /tmp/rn|wc -c
4973229

;# 7z mx9 gets it to 4646598

This data is a series of DNA sequencing read identifiers, looking like:

VP2-06:112:H7LNDMCVY:1:1124:21694:10473
VP2-06:112:H7LNDMCVY:1:1158:23665:6370
VP2-06:112:H7LNDMCVY:1:1219:23746:16250
VP2-06:112:H7LNDMCVY:1:1243:16414:36119
VP2-06:112:H7LNDMCVY:1:1251:6253:36119
VP2-06:112:H7LNDMCVY:1:1324:31412:16595
VP2-06:112:H7LNDMCVY:1:1431:22119:16125
VP2-06:112:H7LNDMCVY:1:2152:28881:21512
VP2-06:112:H7LNDMCVY:1:2207:21287:33567
VP2-06:112:H7LNDMCVY:1:2219:32651:24940
...

There are periodic duplicates as the data is paired, typically 50-150 lines apart.
There are lots of spurious matches in the rather random looking numbers (X and Y locations on a slide) which we're not interested in deflating, while the main prefix is critical. I think exposing the minimum match length, albeit in multiple places and I haven't a clue on the btree version, is a simple tweak to gain more out of the library.

Does this sound like something you'd consider adding?

Edit: with optimal parsing disabled and gzip -9 it gets "4977440" using min match of 7. Pretty close to zlib (I think that has min match of 5 though).

Edit: Fixed formatting.

If -V option is included in gzip command line, program does not compress the file(s)

Hi Eric:

I'm using your posted Windows 64-bit binaries of libdeflate 0.7. When using the gzip program, if I include the -V flag to get version and legal info, either by itself or in combination with other flags (e.g. -kV), the file is not compressed, no .gz file is produced, etc.

All that happens is that the version and legal info is displayed, as though -V was the sole content of the command. See the example below:

PS C:\Tools\libdeflate-0.7> .\gzip -12 -k -V jQuery-3.2.1-min-CDNJS.js
gzip compression program v0.7
Copyright 2016 Eric Biggers

This program is free software which may be modified and/or redistributed
under the terms of the MIT license.  There is NO WARRANTY, to the extent
permitted by law.  See the COPYING file for details.
PS C:\Tools\libdeflate-0.7>

This is in Powershell on Windows 10, 64-bit. As I mentioned, I'm using your posted Windows binaries as opposed to my own builds.

If I simply remove the -V flag, the gzip program works as expected, I get a compressed file, etc.

Ideas?

Maximum compression

HI!
Tell me, how it is possible to increase extent of compression?

$ time /c/Users/Lorents/Desktop/gzip.exe -12 /c/Users/Lorents/Desktop/enwik8

Archive size: 35 215 350 bytes (34 MiB)

real    0m17.382s
user    0m0.000s
sys     0m0.000s
$ time '/c/Program Files/7-Zip/7z.exe' a -tgzip -mx=9 -mfb=258 -mpass=1 /c/Users/Lorents/Desktop/enwik8.gz /c/Users/Lorents/Desktop/enwik8

7-Zip [64] 16.00 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-10

Archive size: 35 144 526 bytes (34 MiB)

real    0m17.613s
user    0m0.000s
sys     0m0.000s

Steaming; PGO

Hi Eric – libdeflate is hitting incredible performance numbers now. Are you still opposed to a streaming implementation? It would come in very handy, especially since the other zlib forks (Cloudflare's, zlib-ng, Intel's) don't seem to be usable on typical servers like nginx.

Also, have you tried profile guided optimization in gcc? If not, do you anticipate any wins there? libdeflate is already hitting incredible numbers, so maybe there isn't much headroom left, but I've been reading up on PGO in gcc 5/6 and was curious. I'll probably try it at some point. I've also discovered the source code annotations that gcc supports, but I doubt they would make much difference here. (The final frontier might be STOKE: https://github.com/StanfordPL/stoke)

wrong detection of AVX512

adler32.c compilation fails on Ubuntu 14.04 but not on 16.04 with the same gcc-5 version:
https://travis-ci.org/inikep/lzbench/jobs/602079354

gcc-5  -Wno-unknown-pragmas -Wno-sign-compare -Wno-conversion -fomit-frame-pointer -fstrict-aliasing -ffast-math -O3 -DNDEBUG libdeflate/adler32.c -std=c99 -c -o libdeflate/adler32.o
/tmp/ccM6MhGs.s: Assembler messages:
/tmp/ccM6MhGs.s:428: Error: operand type mismatch for `vpmaddubsw'
/tmp/ccM6MhGs.s:429: Error: operand type mismatch for `vpsadbw'
/tmp/ccM6MhGs.s:431: Error: operand type mismatch for `vpmaddwd'

Probable reason is Some platforms support AVX512F but not AVX512BW:
microsoft/onnxruntime#2083

filename and timestamps storing

Hey,
is gzip able to save file name or time stams of compressed file?
I looked into options but there seem to be nothing which suggests there is no such option.

libdeflate_gzip_compress fails for 32-bit windows builds

Getting an exception when using the pre-built windows dll [1.0] (called from C#).
64 bit gzip works.
32 bit and 64 bit deflate works.
My implementation is identical for gzip and deflate (with exception of the function calls to the DLL).

"System.AccessViolationException [0x80004003] Attempted to read or write protected memory. This is often an indication that other memory is corrupt."

Tested with a bunch of data files from the Silesia corpus ("dickens", "xml", "mozilla" etc).

decompress_result clash with xpack

This is a minor issue, but I was trying to add libdeflate to lzbench, which already contains your xpack library. I ran into an issue with the decompress_result enum, which is the same in both. Since enum names and values are in the global namespace, I can't include both public headers at the same time.

Allow controlling the setting at which libdeflate only emits an uncompressed deflate stream

libdeflate has truly entered the mainstream when it pops up in Minecraft, as I do in Velocity 1.1.0. In Minecraft, there is a need for fast, real-time compression, and libdeflate fills an important need for accelerating the zlib/deflate-based compression used by the game's protocol.

I recently ran across a need to use libdeflate in the protocol of Minecraft: Bedrock Edition. This game is... strange, and it's not a natural fit for libdeflate's block-based decompression. In this particular edition of the game, though, everything is deflate-compressed and this wastes CPU. While libdeflate by default only emits uncompressed deflate streams for inputs that are less than 16 bytes in length, this still wastes quite a bit of CPU on our end for the small packets the game often sends and we had a need to raise this to 128 bytes. For now, we run a modified libdeflate where we patched the relevant check but we'd like to make it configurable if possible so we can run vanilla libdeflate.

Thanks for making this library, it's greatly appreciated.

Deflat Compressor Length

Hi there dear @ebiggers
First thank you for this amazing library, I just came from zlib to your library and I have some difficulties.
I want to do a very simple deflate compression on a buffer and I can't figure it out how to deal with length.

I know there's two way to deal with length in gzip and lz4 , I worked with them before and I was adding original data size as a little header in my compressed data but In this case every single byte is important to me.

In C# there's a internal compressor known as DeflatStream we just pass a byte array and get a byte array back :

public static byte[] Compress(byte[] data)
{
	MemoryStream output = new MemoryStream();
	using (DeflateStream dstream = new DeflateStream(output, CompressionLevel.Optimal))
	{
		dstream.Write(data, 0, data.Length);
	}
	return output.ToArray();
}
public static byte[] Decompress(byte[] data)
{
	MemoryStream input = new MemoryStream(data);
	MemoryStream output = new MemoryStream();
	using (DeflateStream dstream = new DeflateStream(input, CompressionMode.Decompress))
	{
		dstream.CopyTo(output);
	}
	return output.ToArray();
}

Result data doesn't contain any thing related to original size data.
So I tried to do the same using libdeflate and here's my current code :

#include <iostream>
#include <vector>
#include <fstream>

#include "libdeflate.h"
#pragma comment( lib , "libdeflatestatic.lib" )

using namespace std;

#define LOG(x) printf("%s\n",x)
#define LOGVAL(valname,val) printf("Value `%s` = %d\n",valname,val)

int main() 
{
	struct libdeflate_compressor* compressor;
	struct libdeflate_decompressor* decompressor;
	ofstream fout;

	std::ifstream input("inputdata.dta", std::ios::binary);

	std::vector<unsigned char> buffer(std::istreambuf_iterator<char>(input), {});

	const int originalDataSize = buffer.size();

	// Compress
	compressor = libdeflate_alloc_compressor(9);
	std::vector<unsigned char> outdata;
	outdata.resize(originalDataSize);

	LOG("Compressing...");
	int cmpsize = libdeflate_deflate_compress(compressor, buffer.data(), originalDataSize, outdata.data(), originalDataSize);

	LOGVAL("cmpsize",cmpsize);

	fout.open("compressed.bin", ios::binary | ios::out);
	fout.write((char*)outdata.data(), cmpsize);
	fout.close();

	libdeflate_free_compressor(compressor);

	// Decompress
	size_t dec_size;
	std::vector<unsigned char> dec_outdata;
	dec_outdata.resize(originalDataSize);

	decompressor = libdeflate_alloc_decompressor();
	libdeflate_deflate_decompress(decompressor, outdata.data(), cmpsize, dec_outdata.data(), originalDataSize, &dec_size);

	fout.open("decompressed.bin", ios::binary | ios::out);
	fout.write((char*)dec_outdata.data(), dec_size);
	fout.close();

	libdeflate_free_decompressor(decompressor);

	LOG("App finished.");
}

As you can see I always need originalDataSize to make compression/decompression work well, I don't know if I'm doing something wrong or not but I need to do it like how C# DeflateStream works, I need to pass a new vector or byte array without knowing original size and do the decompression.

I want to have a pure deflate result in compression with out adding any metadata or extra information I will be very greatful if you tell me how is this possible in c++ within your library.

Regards,
Ultran

Libdeflate vs ECT

File: enwik8, 100,000,000 bytes, compressed into gzip format

Compressor File Size Time
gzip -12 35 100 553 byte 22.608s
ect -2 35 350 269 byte 23.478s
ect -3 35 013 879 byte 30.082s
ect -4 34 967 607 byte 35.125s

Tell me, it is planned to increase compression level?

MinGW_w64 make errors with cr and libdeflate.lib

On a new machine (Windows 10), I'm getting the following errors when trying to build:

PS C:\Repos\libdeflate-master> C:\mingw64-win32\bin\mingw32-make.exe CC=x86_64-w64-mingw32-gcc-6.3.0
  CC       lib/aligned_malloc.o
  CC       lib/deflate_decompress.o
  CC       lib/x86_cpu_features.o
  CC       lib/deflate_compress.o
  CC       lib/adler32.o
  CC       lib/zlib_decompress.o
  CC       lib/zlib_compress.o
  CC       lib/crc32.o
  CC       lib/gzip_decompress.o
  CC       lib/gzip_compress.o
  AR       libdeflate.lib
x86_64-w64-mingw32-gcc-6.3.0.exe: error: cr: No such file or directory
x86_64-w64-mingw32-gcc-6.3.0.exe: error: libdeflate.lib: No such file or directory
Makefile:122: recipe for target 'libdeflate.lib' failed
mingw32-make: *** [libdeflate.lib] Error 1

I don't understand what cr is, but libdeflate.lib seems to be part of the cleaning phase. Any idea how to get past these?

FYI, I'm using MinGW_w64 obtained from this official page, specifically the x86_64-win32-seh version.

Your StdCall function names have weird suffix, and VB6 doesn't like it.

Thanks for putting StdCall functions in the 32bit Windows version. However this has its own problem now. The functions now contain a suffix in the name of the function itself. For example, the function libdeflate_crc32 is now called libdeflate_crc32@12. Is there some way for you to tell your compiler to not add these numbers and @ symbols at the end of the function names? The @ symbol makes a problem for VB6, which is the programming language I'm using. VB6 does not allow an functions to contain the @ symbol in the function name. All of the Windows API functions that work in VB6 are StdCall functions, but none of the Windows API functions contain a suffix like this. They don't have an @ symbol followed by a number. One example is the Windows API function VirtualAlloc in kernel32.dll which is used to allocate a block of virtual memory. It's not something like VirtualAlloc@12. It's just plain VirtualAlloc.

compilation error - gcc does not see definitions from standard headers

I tried to compile libdeflate and although I thought it will be no brainer (just make && make install), it wasn't.

	$ make
	In file included from programs/gzip.c:28:0:
	programs/prog_util.h:145:1: error: unknown type name ‘ssize_t’

	programs/gzip.c: In function ‘restore_mode’:
	programs/gzip.c:264:2: warning: implicit declaration of function ‘fchmod’ [-Wimplicit-function-declaration]  // what are these anyway?
	programs/gzip.c: In function ‘restore_owner_and_group’:
	programs/gzip.c:273:2: warning: implicit declaration of function ‘fchown’ [-Wimplicit-function-declaration]

so I found it eventually that ‘ssize_t’ is declared in <unistd.h> and added it in `prog_util.h’

	$make
	programs/prog_util.c: In function ‘xopen_for_read’:
	programs/prog_util.c:235:2: warning: implicit declaration of function ‘posix_fadvise’ [-Wimplicit-function-declaration]
	programs/prog_util.c:235:32: error: ‘POSIX_FADV_SEQUENTIAL’ undeclared (first use in this function)
	programs/prog_util.c:235:32: note: each undeclared identifier is reported only once for each function it appears in
	programs/prog_util.c: In function ‘map_file_contents’:
	programs/prog_util.c:396:2: warning: implicit declaration of function ‘posix_madvise’ [-Wimplicit-function-declaration]
	programs/prog_util.c:396:38: error: ‘POSIX_MADV_SEQUENTIAL’ undeclared (first use in this function)

‘POSIX_FADV_SEQUENTIAL’ is in <fcntl.> which is included
‘POSIX_MADV_SEQUENTIAL’ is in <sys/mman.h> which also is included

So now I have no idea what to do with it - for me it should compile without problems - these values are properly defined in standard headers. Any idea how to solve it or what I do wrong?

MinGW/make errors

Hello – I've not found any way to compile on Windows using the MinGW64 toolchain. If I use make as described in the ReadMe, I get the following errors:

-Wpedantic was unexpected at this time.
-Wdeclaration-after-statement was unexpected at this time.
-Wmissing-prototypes was unexpected at this time.
-Wstrict-prototypes was unexpected at this time.
-Wvla was unexpected at this time.
'flags' is not recognized as an internal or external command,
operable program or batch file.
make: *** [Makefile:137: .lib-cflags] Error 1

Any ideas? I'm on Windows 10 64-bit, using Stephan Lavavej's 64-bit MinGW bundle, which uses GCC 6.1 (though I don't think GCC is yet making an appearance given the above errors).

Could you compile a second version with StdCall?

I know you use Cdecl as the calling convention now, but could you also add a second parallel branch to your project, with StdCall? I need the functionality of libdeflate, without the burden of writing using C as my programming language. I use VB6 (yes it's old, but it works fine for 99% of what I do) and VB6 requires StdCall. Unlike in C, in VB6 there's no option of importing a DLL function that uses the Cdecl calling convention. It's either StdCall, or the function CAN'T be called. The ONLY time I use C or C++ is when I want to write code better optimized for speed, but at the expense of it being much more difficult to write the program. For everything else I use VB6. With C++ you can't just create a window and add buttons. You need to spend days of coding just to create the window, add buttons, and program it to even be able to respond to button clicking (this means detecting and responding to window messages). In VB6, the ONLY code you need to write that tells it what to do when a button is clicked. The actual act of detecting a button click is part of the code that is automatically generated by VB6 itself, as is code that corresponds to creating and displaying the window and adding and displaying buttons on that window. You literally just drag-drop buttons (and other controls) onto the window, and internally VB6 generates all the code that is needed to handle these controls.

So please don't ask me to migrate to C or C++ for my programming needs. That's not going to happen. I need you instead compile a separate branch of libdeflate, which is the same as the main branch in every way but one, and that one way is that the functions must be StdCall functions instead of Cdecl functions.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.