Skip to content

Commit 83265b3

Browse files
committed
zlib: Add support for building with Chromium's zlib implementation
This change builds libgit2 using Chromium's zlib implementation by invoking cmake with `-DUSE_BUNDLED_ZLIB=ON -DUSE_CHROMIUM_ZLIB=ON`, which is ~10% faster than the bundled zlib for the core::zstream suite. This version of zlib has some optimizations: a) Decompression (Intel+ARM): inflate_fast, adler32, crc32, etc. b) Compression (Intel): fill_window, longest_match, hash function, etc. Due to the introduction of SIMD optimizations, and to get the maximum performance out of this fork of zlib, this requires an x86_64 processor with SSE4.2 and CLMUL (anything Westmere or later, ~2010). The Chromium zlib implementation also supports ARM with NEON, but it has not been enabled in this patch. Performance =========== TL;DR: Running just `./libgit2_clar -score::zstream` 100 times in a loop took 0:56.30 before and 0:50.67 after (~10% reduction!). The bundled and system zlib implementations on an Ubuntu Focal system perform relatively similar (the bundled one is marginally better due to the compiler being able to inline some functions), so only the bundled and Chromium zlibs were compared. For a more balanced comparison (to ensure that nothing regressed overall), `libgit2_clar` under `perf` was also run, and the zlib-related functions were compared. Bundled ------- ```shell cmake \ -DUSE_BUNDLED_ZLIB=ON \ -DUSE_CHROMIUM_ZLIB=OFF \ -DCMAKE_BUILD_TYPE="RelWithDebInfo" \ -DCMAKE_C_FLAGS="-fPIC -fno-omit-frame-pointer" \ -GNinja \ .. ninja perf record --call-graph=dwarf ./libgit2_clar perf report --children ``` ``` Samples: 87K of event 'cycles', Event count (approx.): 75923450603 Children Self Command Shared Objec Symbol + 4.14% 0.01% libgit2_clar libgit2_clar [.] git_zstream_get_output_chunk + 2.91% 0.00% libgit2_clar libgit2_clar [.] git_zstream_get_output + 0.69% 0.00% libgit2_clar libgit2_clar [.] git_zstream_get_output (inlined) 0.17% 0.00% libgit2_clar libgit2_clar [.] git_zstream_init 0.02% 0.00% libgit2_clar libgit2_clar [.] git_zstream_reset 0.00% 0.00% libgit2_clar libgit2_clar [.] git_zstream_eos 0.00% 0.00% libgit2_clar libgit2_clar [.] git_zstream_done 0.00% 0.00% libgit2_clar libgit2_clar [.] git_zstream_free (inlined) Samples: 87K of event 'cycles', Event count (approx.): 75923450603 Children Self Command Shared Objec Symbol + 3.12% 0.01% libgit2_clar libgit2_clar [.] deflate + 2.65% 1.48% libgit2_clar libgit2_clar [.] deflate_slow + 1.60% 0.55% libgit2_clar libgit2_clar [.] inflate + 0.53% 0.00% libgit2_clar libgit2_clar [.] write_deflate 0.49% 0.36% libgit2_clar libgit2_clar [.] inflate_fast 0.46% 0.02% libgit2_clar libgit2_clar [.] deflate_fast 0.19% 0.19% libgit2_clar libgit2_clar [.] inflate_table 0.16% 0.01% libgit2_clar libgit2_clar [.] inflateInit_ 0.15% 0.00% libgit2_clar libgit2_clar [.] inflateInit2_ (inlined) 0.10% 0.00% libgit2_clar libgit2_clar [.] deflateInit_ 0.10% 0.00% libgit2_clar libgit2_clar [.] deflateInit2_ 0.03% 0.00% libgit2_clar libgit2_clar [.] deflateReset (inlined) 0.02% 0.00% libgit2_clar libgit2_clar [.] deflateReset 0.02% 0.00% libgit2_clar libgit2_clar [.] inflateEnd 0.02% 0.00% libgit2_clar libgit2_clar [.] deflateEnd 0.01% 0.00% libgit2_clar libgit2_clar [.] deflateResetKeep 0.01% 0.01% libgit2_clar libgit2_clar [.] inflateReset2 0.01% 0.00% libgit2_clar libgit2_clar [.] deflateReset (inlined) 0.00% 0.00% libgit2_clar libgit2_clar [.] inflateStateCheck (inlined) 0.00% 0.00% libgit2_clar libgit2_clar [.] inflateReset (inlined) 0.00% 0.00% libgit2_clar libgit2_clar [.] inflateStateCheck (inlined) 0.00% 0.00% libgit2_clar libgit2_clar [.] deflateStateCheck (inlined) 0.00% 0.00% libgit2_clar libgit2_clar [.] inflateResetKeep (inlined) ``` Chromium -------- ```shell cmake \ -DUSE_BUNDLED_ZLIB=ON \ -DUSE_CHROMIUM_ZLIB=ON \ -DCMAKE_BUILD_TYPE="RelWithDebInfo" \ -DCMAKE_C_FLAGS="-fPIC -fno-omit-frame-pointer" \ -GNinja \ .. ninja perf record --call-graph=dwarf ./libgit2_clar perf report --children ``` ``` Samples: 97K of event 'cycles', Event count (approx.): 80862210917 Children Self Command Shared Objec Symbol + 3.31% 0.00% libgit2_clar libgit2_clar [.] git_zstream_get_output_chunk + 2.27% 0.01% libgit2_clar libgit2_clar [.] git_zstream_get_output + 0.55% 0.00% libgit2_clar libgit2_clar [.] git_zstream_get_output (inlined) 0.18% 0.00% libgit2_clar libgit2_clar [.] git_zstream_init 0.02% 0.00% libgit2_clar libgit2_clar [.] git_zstream_reset 0.00% 0.00% libgit2_clar libgit2_clar [.] git_zstream_free (inlined) 0.00% 0.00% libgit2_clar libgit2_clar [.] git_zstream_done 0.00% 0.00% libgit2_clar libgit2_clar [.] git_zstream_free Samples: 97K of event 'cycles', Event count (approx.): 80862210917 Children Self Command Shared Objec Symbol + 2.55% 0.01% libgit2_clar libgit2_clar [.] deflate + 2.25% 1.41% libgit2_clar libgit2_clar [.] deflate_slow + 1.10% 0.52% libgit2_clar libgit2_clar [.] inflate 0.36% 0.00% libgit2_clar libgit2_clar [.] write_deflate 0.30% 0.03% libgit2_clar libgit2_clar [.] deflate_fast 0.28% 0.15% libgit2_clar libgit2_clar [.] inflate_fast_chunk_ 0.19% 0.19% libgit2_clar libgit2_clar [.] inflate_table 0.17% 0.01% libgit2_clar libgit2_clar [.] inflateInit_ 0.16% 0.00% libgit2_clar libgit2_clar [.] inflateInit2_ (inlined) 0.15% 0.00% libgit2_clar libgit2_clar [.] deflateInit_ 0.15% 0.00% libgit2_clar libgit2_clar [.] deflateInit2_ 0.11% 0.01% libgit2_clar libgit2_clar [.] adler32_z 0.09% 0.09% libgit2_clar libgit2_clar [.] adler32_simd_ 0.05% 0.00% libgit2_clar libgit2_clar [.] deflateReset (inlined) 0.05% 0.00% libgit2_clar libgit2_clar [.] deflate_read_buf 0.03% 0.00% libgit2_clar libgit2_clar [.] inflateEnd 0.02% 0.00% libgit2_clar libgit2_clar [.] deflateReset 0.01% 0.00% libgit2_clar libgit2_clar [.] deflateEnd 0.01% 0.01% libgit2_clar libgit2_clar [.] inflateReset2 0.01% 0.00% libgit2_clar libgit2_clar [.] inflateReset (inlined) 0.00% 0.00% libgit2_clar libgit2_clar [.] adler32 0.00% 0.00% libgit2_clar libgit2_clar [.] inflateResetKeep (inlined) 0.00% 0.00% libgit2_clar libgit2_clar [.] deflateResetKeep 0.00% 0.00% libgit2_clar libgit2_clar [.] inflateStateCheck (inlined) 0.00% 0.00% libgit2_clar libgit2_clar [.] inflateStateCheck (inlined) 0.00% 0.00% libgit2_clar libgit2_clar [.] inflateStateCheck (inlined) 0.00% 0.00% libgit2_clar libgit2_clar [.] deflateStateCheck (inlined) ```
1 parent fe41e58 commit 83265b3

File tree

3 files changed

+113
-4
lines changed

3 files changed

+113
-4
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ OPTION(USE_LEAK_CHECKER "Run tests with leak checker" OFF)
5151
OPTION(DEBUG_POOL "Enable debug pool allocator" OFF)
5252
OPTION(ENABLE_WERROR "Enable compilation with -Werror" OFF)
5353
OPTION(USE_BUNDLED_ZLIB "Use the bundled version of zlib" OFF)
54+
OPTION(USE_CHROMIUM_ZLIB "If using the bundled version of zlib, use the Chromium flavor (x86_64 processor with SSE4.2 and CLMUL required)" OFF)
5455
SET(USE_HTTP_PARSER "" CACHE STRING "Specifies the HTTP Parser implementation; either system or builtin.")
5556
OPTION(DEPRECATE_HARD "Do not include deprecated functions in the library" OFF)
5657
SET(REGEX_BACKEND "" CACHE STRING "Regular expression implementation. One of regcomp_l, pcre2, pcre, regcomp, or builtin.")

deps/chromium-zlib/CMakeLists.txt

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
# CMake build script for the bundled Chromium zlib implementation. So far, it
2+
# is only supported for x86_64 processors with CLMUL, SSE3, SSE4.2.
3+
#
4+
# TODO: The Chromium build file (in deps/chromium-zlib/zlib/BUILD.gn) supports
5+
# more platforms (like ARM with NEON), more can be enabled as needed.
6+
7+
CMAKE_MINIMUM_REQUIRED(VERSION 3.11)
8+
9+
include(FetchContent)
10+
include(FindGit)
11+
12+
# Ensure that the git binary is present to download the sources.
13+
find_package(Git)
14+
IF(NOT Git_FOUND)
15+
message(FATAL_ERROR "git is required to download the Chromium zlib sources")
16+
ENDIF()
17+
18+
FetchContent_Populate(chromium_zlib_src
19+
GIT_REPOSITORY https://chromium.googlesource.com/chromium/src/third_party/zlib.git
20+
GIT_TAG 2c183c9f93a328bfb3121284da13cf89a0f7e64a
21+
QUIET
22+
)
23+
24+
# The Chromium build globally disables some warnings.
25+
disable_warnings(implicit-fallthrough)
26+
disable_warnings(unused-function)
27+
disable_warnings(unused-parameter)
28+
disable_warnings(sign-compare)
29+
disable_warnings(declaration-after-statement)
30+
disable_warnings(missing-declarations)
31+
32+
# -O3 is also set by the Chromium configuration and has been deemed safe enough
33+
# for them.
34+
SET(CMAKE_C_FLAGS_RELWITHDEBINFO "-O3 -g -DNDEBUG")
35+
SET(CMAKE_C_FLAGS_RELEASE "-O3 -DNDEBUG")
36+
37+
# Common definitions.
38+
add_definitions(
39+
-DSTDC
40+
-DNO_GZIP
41+
-DZLIB_IMPLEMENTATION
42+
)
43+
list(APPEND SRC_ZLIB
44+
"${chromium_zlib_src_SOURCE_DIR}/adler32.c"
45+
"${chromium_zlib_src_SOURCE_DIR}/chromeconf.h"
46+
"${chromium_zlib_src_SOURCE_DIR}/compress.c"
47+
"${chromium_zlib_src_SOURCE_DIR}/contrib/optimizations/insert_string.h"
48+
"${chromium_zlib_src_SOURCE_DIR}/cpu_features.c"
49+
"${chromium_zlib_src_SOURCE_DIR}/cpu_features.h"
50+
"${chromium_zlib_src_SOURCE_DIR}/crc32.c"
51+
"${chromium_zlib_src_SOURCE_DIR}/crc32.h"
52+
"${chromium_zlib_src_SOURCE_DIR}/deflate.c"
53+
"${chromium_zlib_src_SOURCE_DIR}/deflate.h"
54+
"${chromium_zlib_src_SOURCE_DIR}/gzclose.c"
55+
"${chromium_zlib_src_SOURCE_DIR}/gzguts.h"
56+
"${chromium_zlib_src_SOURCE_DIR}/gzlib.c"
57+
"${chromium_zlib_src_SOURCE_DIR}/gzread.c"
58+
"${chromium_zlib_src_SOURCE_DIR}/gzwrite.c"
59+
"${chromium_zlib_src_SOURCE_DIR}/infback.c"
60+
"${chromium_zlib_src_SOURCE_DIR}/inffast.c"
61+
"${chromium_zlib_src_SOURCE_DIR}/inffast.h"
62+
"${chromium_zlib_src_SOURCE_DIR}/inffixed.h"
63+
"${chromium_zlib_src_SOURCE_DIR}/inflate.h"
64+
"${chromium_zlib_src_SOURCE_DIR}/inftrees.c"
65+
"${chromium_zlib_src_SOURCE_DIR}/inftrees.h"
66+
"${chromium_zlib_src_SOURCE_DIR}/trees.c"
67+
"${chromium_zlib_src_SOURCE_DIR}/trees.h"
68+
"${chromium_zlib_src_SOURCE_DIR}/uncompr.c"
69+
"${chromium_zlib_src_SOURCE_DIR}/zconf.h"
70+
"${chromium_zlib_src_SOURCE_DIR}/zlib.h"
71+
"${chromium_zlib_src_SOURCE_DIR}/zutil.c"
72+
"${chromium_zlib_src_SOURCE_DIR}/zutil.h"
73+
)
74+
75+
# x86_64-specific optimizations
76+
string(APPEND CMAKE_C_FLAGS " -mssse3 -msse4.2 -mpclmul")
77+
add_definitions(
78+
-DCHROMIUM_ZLIB_NO_CHROMECONF
79+
-DX86_NOT_WINDOWS
80+
-DADLER32_SIMD_SSSE3
81+
-DCRC32_SIMD_SSE42_PCLMUL
82+
-DDEFLATE_FILL_WINDOW_SSE2
83+
-DINFLATE_CHUNK_READ_64LE
84+
-DINFLATE_CHUNK_SIMD_SSE2
85+
)
86+
list(APPEND SRC_ZLIB
87+
"${chromium_zlib_src_SOURCE_DIR}/adler32_simd.c"
88+
"${chromium_zlib_src_SOURCE_DIR}/adler32_simd.h"
89+
"${chromium_zlib_src_SOURCE_DIR}/contrib/optimizations/chunkcopy.h"
90+
"${chromium_zlib_src_SOURCE_DIR}/contrib/optimizations/inffast_chunk.c"
91+
"${chromium_zlib_src_SOURCE_DIR}/contrib/optimizations/inffast_chunk.h"
92+
"${chromium_zlib_src_SOURCE_DIR}/contrib/optimizations/inflate.c"
93+
"${chromium_zlib_src_SOURCE_DIR}/crc32_simd.c"
94+
"${chromium_zlib_src_SOURCE_DIR}/crc32_simd.h"
95+
"${chromium_zlib_src_SOURCE_DIR}/crc_folding.c"
96+
"${chromium_zlib_src_SOURCE_DIR}/fill_window_sse.c"
97+
)
98+
99+
list(SORT SRC_ZLIB)
100+
include_directories("${chromium_zlib_src_SOURCE_DIR}")
101+
add_library(chromium_zlib OBJECT ${SRC_ZLIB})

src/CMakeLists.txt

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -202,10 +202,17 @@ IF(NOT USE_BUNDLED_ZLIB)
202202
ENDIF()
203203
ENDIF()
204204
IF(USE_BUNDLED_ZLIB OR NOT ZLIB_FOUND)
205-
ADD_SUBDIRECTORY("${libgit2_SOURCE_DIR}/deps/zlib" "${libgit2_BINARY_DIR}/deps/zlib")
206-
LIST(APPEND LIBGIT2_INCLUDES "${libgit2_SOURCE_DIR}/deps/zlib")
207-
LIST(APPEND LIBGIT2_OBJECTS $<TARGET_OBJECTS:zlib>)
208-
ADD_FEATURE_INFO(zlib ON "using bundled zlib")
205+
IF(USE_CHROMIUM_ZLIB)
206+
ADD_SUBDIRECTORY("${libgit2_SOURCE_DIR}/deps/chromium-zlib" "${libgit2_BINARY_DIR}/deps/chromium-zlib")
207+
LIST(APPEND LIBGIT2_INCLUDES "${libgit2_SOURCE_DIR}/deps/chromium-zlib")
208+
LIST(APPEND LIBGIT2_OBJECTS $<TARGET_OBJECTS:chromium_zlib>)
209+
ADD_FEATURE_INFO(zlib ON "using (Chromium) bundled zlib")
210+
ELSE()
211+
ADD_SUBDIRECTORY("${libgit2_SOURCE_DIR}/deps/zlib" "${libgit2_BINARY_DIR}/deps/zlib")
212+
LIST(APPEND LIBGIT2_INCLUDES "${libgit2_SOURCE_DIR}/deps/zlib")
213+
LIST(APPEND LIBGIT2_OBJECTS $<TARGET_OBJECTS:zlib>)
214+
ADD_FEATURE_INFO(zlib ON "using bundled zlib")
215+
ENDIF()
209216
ENDIF()
210217

211218
# Optional external dependency: libssh2

0 commit comments

Comments
 (0)