From b22f94b563085a165191d9fa78eaef594f2ad125 Mon Sep 17 00:00:00 2001 From: Nils Homer Date: Mon, 22 Jun 2026 12:01:35 -0700 Subject: [PATCH] perf: build htslib with libdeflate for faster BGZF/BAM decoding make_examples spends a large fraction of wall time in zlib decompressing BGZF blocks while reading the input BAM. Building htslib against libdeflate (its supported fast DEFLATE codec, as used by samtools) moves BGZF decode off zlib and onto libdeflate's BMI2-optimized decompressor. Measured ~7% faster make_examples on a 30x WGS chr22:20-30Mb slice (5:33.7 -> 5:10.4, best of 2 reps, same host, back-to-back). libdeflate 1.20 is vendored hermetically via http_archive (matching how htslib itself is vendored); HAVE_LIBDEFLATE is enabled in the htslib config and @libdeflate is added to its deps. libdeflate is MIT-licensed. DEFLATE decompression is bit-exact per RFC 1951, so output is unchanged. --- WORKSPACE | 13 +++++++++++++ third_party/htslib.BUILD | 6 +++++- third_party/libdeflate.BUILD | 23 +++++++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 third_party/libdeflate.BUILD diff --git a/WORKSPACE b/WORKSPACE index 6855d4ddb..44a6ac937 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -29,6 +29,19 @@ http_archive( ], ) +# libdeflate is a faster DEFLATE/gzip codec than zlib. htslib uses it for bgzf +# (BAM) (de)compression when built with HAVE_LIBDEFLATE; BAM bgzf decoding is the +# dominant codec cost when reading reads in make_examples. +http_archive( + name = "libdeflate", + build_file = "//:third_party/libdeflate.BUILD", + sha256 = "ed1454166ced78913ff3809870a4005b7170a6fd30767dc478a09b96847b9c2a", + strip_prefix = "libdeflate-1.20", + urls = [ + "https://github.com/ebiggers/libdeflate/archive/refs/tags/v1.20.tar.gz", + ], +) + http_archive( name = "libssw", build_file = "//:third_party/libssw.BUILD", diff --git a/third_party/htslib.BUILD b/third_party/htslib.BUILD index 17da8679f..65cbadf40 100644 --- a/third_party/htslib.BUILD +++ b/third_party/htslib.BUILD @@ -217,6 +217,7 @@ genrule( echo '#define HAVE_GMTIME_R 1' echo '#define HAVE_INTTYPES_H 1' echo '#define HAVE_LIBBZ2 1' + echo '#define HAVE_LIBDEFLATE 1' echo '#define HAVE_LIBLZMA 1' echo '#define HAVE_LIBZ 1' echo '#define HAVE_MEMORY_H 1' @@ -273,7 +274,10 @@ cc_library( linkopts = extra_libs, textual_hdrs = textual_hdrs, visibility = ["//visibility:public"], - deps = [":htslib_deps"], + deps = [ + ":htslib_deps", + "@libdeflate", + ], ) # Misc binaries that might be exported. diff --git a/third_party/libdeflate.BUILD b/third_party/libdeflate.BUILD new file mode 100644 index 000000000..a895c0cb2 --- /dev/null +++ b/third_party/libdeflate.BUILD @@ -0,0 +1,23 @@ +# Description: +# libdeflate - fast DEFLATE/zlib/gzip compression and decompression. +# Used by htslib (when HAVE_LIBDEFLATE is set) to accelerate bgzf (BAM) +# (de)compression. + +licenses(["notice"]) # MIT + +exports_files(["COPYING"]) + +# All architecture-specific sources are guarded by ARCH_* #ifdefs and compile to +# nothing on non-matching targets, so it is safe to compile every lib/**/*.c. +cc_library( + name = "libdeflate", + srcs = glob([ + "lib/**/*.c", + "lib/**/*.h", + "common_defs.h", + ]), + hdrs = ["libdeflate.h"], + copts = ["-O3"], + includes = ["."], + visibility = ["//visibility:public"], +)