Skip to content

Commit 7a37f57

Browse files
authored
Implement HuffmanCodec with LiteSpeed (#12357)
Performance tooling highlights hpack decoding as an expensive operation for us. This improves hpack performance by using the MIT licensed LiteSpeed implementation. Fixes: #12321
1 parent e5e3da8 commit 7a37f57

24 files changed

Lines changed: 136709 additions & 492 deletions

File tree

NOTICE

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,3 +111,10 @@ https://fossies.org/linux/systemtap/includes/sys/sdt.h
111111

112112
tools/ebpf/trylock-stats is try lock version of lockstat-solution.py of goldshtn/linux-tracing-workshop
113113
Copyright (c) 2017 Sasha Goldshtein (MIT License)
114+
115+
~~
116+
117+
LS-HPACK provides functionality to encode and decode HTTP headers using
118+
HPACK compression mechanism specified in RFC 7541.
119+
Copyright (c) 2018 - 2023 LiteSpeed Technologies Inc, (MIT License)
120+
https://github.com/litespeedtech/ls-hpack.git

include/proxy/hdrs/HuffmanCodec.h

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,7 @@
2323

2424
#pragma once
2525

26-
#include <cstddef>
2726
#include <cstdint>
2827

29-
void hpack_huffman_init();
30-
void hpack_huffman_fin();
31-
int64_t huffman_decode(char *dst_start, const uint8_t *src, uint32_t src_len);
32-
uint8_t *huffman_encode_append(uint8_t *dst, uint32_t src, int n);
33-
int64_t huffman_encode(uint8_t *dst_start, const uint8_t *src, uint32_t src_len);
28+
int64_t huffman_decode(char *dst, uint32_t dst_len, uint8_t const *src, uint32_t src_len);
29+
int64_t huffman_encode(uint8_t *dst, uint32_t dst_len, uint8_t const *src, uint32_t src_len);

lib/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,5 @@ target_include_directories(catch2::catch2 INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}
4444

4545
add_library(systemtap::systemtap INTERFACE IMPORTED GLOBAL)
4646
target_include_directories(systemtap::systemtap INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/systemtap")
47+
48+
add_subdirectory(ls-hpack)

lib/ls-hpack/CMakeLists.txt

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#######################
2+
#
3+
# Licensed to the Apache Software Foundation (ASF) under one or more contributor license
4+
# agreements. See the NOTICE file distributed with this work for additional information regarding
5+
# copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0
6+
# (the "License"); you may not use this file except in compliance with the License. You may obtain
7+
# a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software distributed under the License
12+
# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
13+
# or implied. See the License for the specific language governing permissions and limitations under
14+
# the License.
15+
#
16+
#######################
17+
18+
add_library(lshpack STATIC)
19+
target_sources(lshpack PRIVATE lshpack.cc huff-tables.h lshpack.h)
20+
21+
# lshpack.h uses C99 array designators (see the hencs array in huff-tables.h).
22+
# In theory this limits portability because very old compilers that are C89 only
23+
# won't support this. However, the supported compilers for ATS should all be
24+
# modern enough to support this.
25+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-c99-designator")

lib/ls-hpack/README.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# LiteSpeed HPACK in ATS
2+
3+
Originally, ATS included a home-grown HPACK encoder and decoder for HTTP/2
4+
header compression, featuring a custom Huffman coding implementation. As HTTP/2
5+
adoption grew and later with HTTP/3 evolving to QPACK, the need for
6+
high-performance header decompression became critical. Our original Huffman
7+
decoder was simple but performed bit-by-bit processing, which proved to be a
8+
performance bottleneck under heavy traffic.
9+
10+
To address this, we replaced the ATS home-grown version with the open-source,
11+
MIT-licensed LiteSpeed HPACK library. LiteSpeed's implementation trades static
12+
memory (a fixed-size, compile-time-allocated lookup table of 64K entries) for
13+
drastically reduced computation. In `perf top` testing with production traffic,
14+
the CPU usage of the `huffman_decode` function dropped from about 1% to
15+
effectively unmeasurable levels, delivering a significant performance
16+
improvement.
17+
18+
This integration maintains full HPACK compliance for HTTP/2 and seamlessly
19+
supports header compression performance for HTTP/3 (QPACK), leveraging the same
20+
Huffman decoding acceleration.
21+
22+
# LiteSpeed Version
23+
24+
The current implementation pulled into ATS is based upon what is currently the
25+
latest version,
26+
[v2.3.4](https://github.com/litespeedtech/ls-hpack/releases/tag/v2.3.4).

0 commit comments

Comments
 (0)