Skip to content

Commit 4da30ff

Browse files
committed
Add:maptool:Compress with libdeflate when it is available
libdeflate produces the same raw deflate format as zlib, only faster. The library is optional: without it, maptool compresses with zlib as before. Ubuntu ships the library as libdeflate-dev. A benchmark on 400 real tiles of a map of France, 38.4 MB: codec time size against zlib level 9 zlib 9 4.99 s +-0.0% zlib 6 1.42 s +1.0% libdeflate 9 1.14 s -0.2% libdeflate 6 0.32 s -0.6% libdeflate 12 5.18 s -10.9% Level 6 of libdeflate is 15.6 times faster than level 9 of zlib and the result is smaller. Level 12 needs the time of zlib level 9 and gives a map that is 11 percent smaller, which helps a map that comes near the 2 GiB limit of a GitHub release asset. Measured on a map of Luxembourg with 8 threads and the parallel compression: level 9 of zlib needs 4.9 s for the tiles, level 6 of libdeflate needs 0.7 s. The maps stay semantically identical, every member has a correct CRC, and two runs give identical files.
1 parent 99734ea commit 4da30ff

2 files changed

Lines changed: 36 additions & 2 deletions

File tree

navit/maptool/CMakeLists.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,19 @@ if(BUILD_MAPTOOL)
2424
SET(NAVIT_LIBS ${NAVIT_LIBS} m)
2525
endif(NOT MSVC)
2626

27+
# libdeflate compresses much faster than zlib. It is optional: without it,
28+
# maptool compresses with zlib as before.
29+
find_path(LIBDEFLATE_INCLUDE_DIR libdeflate.h)
30+
find_library(LIBDEFLATE_LIBRARY deflate)
31+
if(LIBDEFLATE_INCLUDE_DIR AND LIBDEFLATE_LIBRARY)
32+
message(STATUS "maptool: compressing with libdeflate (${LIBDEFLATE_LIBRARY})")
33+
set_property(SOURCE zip.c APPEND PROPERTY COMPILE_DEFINITIONS HAVE_LIBDEFLATE=1)
34+
target_include_directories(maptool_core PRIVATE ${LIBDEFLATE_INCLUDE_DIR})
35+
target_link_libraries(maptool_core ${LIBDEFLATE_LIBRARY})
36+
else()
37+
message(STATUS "maptool: libdeflate not found, compressing with zlib")
38+
endif()
39+
2740
target_link_libraries(maptool maptool_core ${NAVIT_LIBNAME} ${NAVIT_LIBS})
2841

2942
install(TARGETS maptool

navit/maptool/zip.c

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828
#include <unistd.h>
2929
#include <zconf.h>
3030
#include <zlib.h>
31+
#ifdef HAVE_LIBDEFLATE
32+
# include <libdeflate.h>
33+
#endif
3134

3235
struct zip_info {
3336
int zipnum;
@@ -49,7 +52,7 @@ static int zip_write(struct zip_info *info, void *data, int len) {
4952
return 1;
5053
}
5154

52-
#ifdef HAVE_ZLIB
55+
#if defined(HAVE_ZLIB) && !defined(HAVE_LIBDEFLATE)
5356
static int compress2_int(Byte *dest, uLongf *destLen, const Bytef *source, uLong sourceLen, int level) {
5457
z_stream stream;
5558
int err;
@@ -101,7 +104,25 @@ void zip_compress_member(struct zip_info *zip_info, char *data, int data_size, s
101104
m->buffer = NULL;
102105
m->crc = crc32(crc32(0, NULL, 0), (unsigned char *)data, data_size);
103106
m->method = zip_info->compression_level ? 8 : 0;
104-
#ifdef HAVE_ZLIB
107+
#ifdef HAVE_LIBDEFLATE
108+
if (zip_info->compression_level) {
109+
/* libdeflate produces the same raw deflate format as the zlib call
110+
* below, only faster. Level 6 of libdeflate compresses tile data
111+
* better than level 9 of zlib. A compressor is not safe for use by
112+
* several threads, so every call allocates its own. */
113+
struct libdeflate_compressor *comp = libdeflate_alloc_compressor(zip_info->compression_level);
114+
size_t destlen = data_size + data_size / 500 + 12;
115+
size_t outlen;
116+
m->buffer = g_malloc(destlen);
117+
outlen = libdeflate_deflate_compress(comp, data, data_size, m->buffer, destlen);
118+
libdeflate_free_compressor(comp);
119+
if (outlen && outlen < (size_t)data_size) {
120+
m->data = m->buffer;
121+
m->data_size = outlen;
122+
} else
123+
m->method = 0;
124+
}
125+
#elif defined(HAVE_ZLIB)
105126
if (zip_info->compression_level) {
106127
uLongf destlen = data_size + data_size / 500 + 12;
107128
int error;

0 commit comments

Comments
 (0)