Skip to content

Commit 687b2eb

Browse files
committed
Perf: Fix mis-usage of Arena in HAPCK
1 parent f905722 commit 687b2eb

File tree

4 files changed

+85
-13
lines changed

4 files changed

+85
-13
lines changed

proxy/hdrs/XPACK.cc

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,3 +200,56 @@ xpack_encode_string(uint8_t *buf_start, const uint8_t *buf_end, const char *valu
200200

201201
return p - buf_start;
202202
}
203+
204+
int64_t
205+
xpack_encode_string(Arena &arena, uint8_t *buf_start, const uint8_t *buf_end, const char *value, uint64_t value_len, uint8_t n)
206+
{
207+
uint8_t *p = buf_start;
208+
bool use_huffman = true;
209+
char *data = nullptr;
210+
int64_t data_len = 0;
211+
212+
// TODO Choose whether to use Huffman encoding wisely
213+
// cppcheck-suppress knownConditionTrueFalse; leaving "use_huffman" for wise huffman usage in the future
214+
if (use_huffman && value_len) {
215+
data = arena.str_alloc(value_len * 4);
216+
data_len = huffman_encode(reinterpret_cast<uint8_t *>(data), reinterpret_cast<const uint8_t *>(value), value_len);
217+
}
218+
219+
// Length
220+
const int64_t len = xpack_encode_integer(p, buf_end, data_len, n);
221+
if (len == -1) {
222+
if (use_huffman) {
223+
arena.str_free(data);
224+
}
225+
226+
return -1;
227+
}
228+
229+
if (use_huffman) {
230+
*p |= 0x01 << n;
231+
} else {
232+
*p &= ~(0x01 << n);
233+
}
234+
p += len;
235+
236+
if (buf_end < p || buf_end - p < data_len) {
237+
if (use_huffman) {
238+
arena.str_free(data);
239+
}
240+
241+
return -1;
242+
}
243+
244+
// Value
245+
if (data_len) {
246+
memcpy(p, data, data_len);
247+
p += data_len;
248+
}
249+
250+
if (use_huffman) {
251+
arena.str_free(data);
252+
}
253+
254+
return p - buf_start;
255+
}

proxy/hdrs/XPACK.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ const static int XPACK_ERROR_SIZE_EXCEEDED_ERROR = -2;
3232
// These primitives are shared with HPACK and QPACK.
3333
int64_t xpack_encode_integer(uint8_t *buf_start, const uint8_t *buf_end, uint64_t value, uint8_t n);
3434
int64_t xpack_decode_integer(uint64_t &dst, const uint8_t *buf_start, const uint8_t *buf_end, uint8_t n);
35+
36+
// TODO: replace all xpack_encode_string() (without Arena) calls in QPACK
3537
int64_t xpack_encode_string(uint8_t *buf_start, const uint8_t *buf_end, const char *value, uint64_t value_len, uint8_t n = 7);
38+
int64_t xpack_encode_string(Arena &arena, uint8_t *buf_start, const uint8_t *buf_end, const char *value, uint64_t value_len,
39+
uint8_t n = 7);
3640
int64_t xpack_decode_string(Arena &arena, char **str, uint64_t &str_length, const uint8_t *buf_start, const uint8_t *buf_end,
3741
uint8_t n = 7);

proxy/http2/HPACK.cc

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,12 @@ HpackIndexingTable::update_maximum_size(uint32_t new_size)
333333
return _dynamic_table->update_maximum_size(new_size);
334334
}
335335

336+
Arena &
337+
HpackIndexingTable::arena()
338+
{
339+
return this->_arena;
340+
}
341+
336342
//
337343
// HpackDynamicTable
338344
//
@@ -538,9 +544,10 @@ encode_literal_header_field_with_indexed_name(uint8_t *buf_start, const uint8_t
538544
p += len;
539545

540546
// Value String
547+
Arena &arena = indexing_table.arena();
541548
int value_len;
542549
const char *value = header.value_get(&value_len);
543-
len = xpack_encode_string(p, buf_end, value, value_len);
550+
len = xpack_encode_string(arena, p, buf_end, value, value_len);
544551
if (len == -1) {
545552
return -1;
546553
}
@@ -581,16 +588,17 @@ encode_literal_header_field_with_new_name(uint8_t *buf_start, const uint8_t *buf
581588

582589
// Convert field name to lower case to follow HTTP2 spec.
583590
// This conversion is needed because WKSs in MIMEFields is old fashioned
584-
Arena arena;
591+
Arena &arena = indexing_table.arena();
585592
int name_len;
586593
const char *name = header.name_get(&name_len);
587-
char *lower_name = arena.str_store(name, name_len);
594+
char *lower_name = arena.str_alloc(name_len);
588595
for (int i = 0; i < name_len; i++) {
589-
lower_name[i] = ParseRules::ink_tolower(lower_name[i]);
596+
lower_name[i] = ParseRules::ink_tolower(name[i]);
590597
}
591598

592599
// Name String
593-
len = xpack_encode_string(p, buf_end, lower_name, name_len);
600+
len = xpack_encode_string(arena, p, buf_end, lower_name, name_len);
601+
arena.str_free(lower_name);
594602
if (len == -1) {
595603
return -1;
596604
}
@@ -599,7 +607,7 @@ encode_literal_header_field_with_new_name(uint8_t *buf_start, const uint8_t *buf
599607
// Value String
600608
int value_len;
601609
const char *value = header.value_get(&value_len);
602-
len = xpack_encode_string(p, buf_end, value, value_len);
610+
len = xpack_encode_string(arena, p, buf_end, value, value_len);
603611
if (len == -1) {
604612
return -1;
605613
}
@@ -647,9 +655,7 @@ decode_indexed_header_field(MIMEFieldWrapper &header, const uint8_t *buf_start,
647655
int decoded_value_len;
648656
const char *decoded_value = header.value_get(&decoded_value_len);
649657

650-
Arena arena;
651-
Debug("hpack_decode", "Decoded field: %s: %s", arena.str_store(decoded_name, decoded_name_len),
652-
arena.str_store(decoded_value, decoded_value_len));
658+
Debug("hpack_decode", "Decoded field: %.*s: %.*s", decoded_name_len, decoded_name, decoded_value_len, decoded_value);
653659
}
654660

655661
return len;
@@ -669,6 +675,7 @@ decode_literal_header_field(MIMEFieldWrapper &header, const uint8_t *buf_start,
669675
int64_t len = 0;
670676
HpackField ftype = hpack_parse_field_type(*p);
671677
bool has_http2_violation = false;
678+
Arena &arena = indexing_table.arena();
672679

673680
if (ftype == HpackField::INDEXED_LITERAL) {
674681
len = xpack_decode_integer(index, p, buf_end, 6);
@@ -686,8 +693,6 @@ decode_literal_header_field(MIMEFieldWrapper &header, const uint8_t *buf_start,
686693

687694
p += len;
688695

689-
Arena arena;
690-
691696
// Decode header field name
692697
if (index) {
693698
indexing_table.get_header_field(index, header);
@@ -697,6 +702,9 @@ decode_literal_header_field(MIMEFieldWrapper &header, const uint8_t *buf_start,
697702

698703
len = xpack_decode_string(arena, &name_str, name_str_len, p, buf_end);
699704
if (len == XPACK_ERROR_COMPRESSION_ERROR) {
705+
if (name_str) {
706+
arena.str_free(name_str);
707+
}
700708
return HPACK_ERROR_COMPRESSION_ERROR;
701709
}
702710

@@ -711,6 +719,7 @@ decode_literal_header_field(MIMEFieldWrapper &header, const uint8_t *buf_start,
711719

712720
p += len;
713721
header.name_set(name_str, name_str_len);
722+
arena.str_free(name_str);
714723
}
715724

716725
// Decode header field value
@@ -719,11 +728,15 @@ decode_literal_header_field(MIMEFieldWrapper &header, const uint8_t *buf_start,
719728

720729
len = xpack_decode_string(arena, &value_str, value_str_len, p, buf_end);
721730
if (len == XPACK_ERROR_COMPRESSION_ERROR) {
731+
if (value_str) {
732+
arena.str_free(value_str);
733+
}
722734
return HPACK_ERROR_COMPRESSION_ERROR;
723735
}
724736

725737
p += len;
726738
header.value_set(value_str, value_str_len);
739+
arena.str_free(value_str);
727740

728741
// Incremental Indexing adds header to header table as new entry
729742
if (isIncremental) {
@@ -737,8 +750,7 @@ decode_literal_header_field(MIMEFieldWrapper &header, const uint8_t *buf_start,
737750
int decoded_value_len;
738751
const char *decoded_value = header.value_get(&decoded_value_len);
739752

740-
Debug("hpack_decode", "Decoded field: %s: %s", arena.str_store(decoded_name, decoded_name_len),
741-
arena.str_store(decoded_value, decoded_value_len));
753+
Debug("hpack_decode", "Decoded field: %.*s: %.*s", decoded_name_len, decoded_name, decoded_value_len, decoded_value);
742754
}
743755

744756
if (has_http2_violation) {

proxy/http2/HPACK.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,10 @@ class HpackIndexingTable
159159
uint32_t size() const;
160160
bool update_maximum_size(uint32_t new_size);
161161

162+
Arena &arena();
163+
162164
private:
165+
Arena _arena;
163166
HpackDynamicTable *_dynamic_table;
164167
};
165168

0 commit comments

Comments
 (0)