Make huffman decoding slightly faster using evil looking macro

This commit is contained in:
Tatsuhiro Tsujikawa 2015-04-26 19:37:57 +09:00
parent 02468b1ca1
commit bbdff112a3
1 changed files with 37 additions and 22 deletions

View File

@ -168,6 +168,23 @@ void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx) {
ctx->accept = 1; ctx->accept = 1;
} }
/* Use macro to make the code simpler..., but error case is tricky.
We spent most of the CPU in decoding, so we are doing this
thing. */
#define hd_huff_decode_sym_emit(bufs, sym, avail) \
do { \
if ((avail)) { \
nghttp2_bufs_fast_addb((bufs), (sym)); \
--(avail); \
} else { \
rv = nghttp2_bufs_addb((bufs), (sym)); \
if (rv != 0) { \
return rv; \
} \
(avail) = nghttp2_bufs_cur_avail((bufs)); \
} \
} while (0)
ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx, ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
nghttp2_bufs *bufs, const uint8_t *src, nghttp2_bufs *bufs, const uint8_t *src,
size_t srclen, int final) { size_t srclen, int final) {
@ -180,30 +197,28 @@ ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
/* We use the decoding algorithm described in /* We use the decoding algorithm described in
http://graphics.ics.uci.edu/pub/Prefix.pdf */ http://graphics.ics.uci.edu/pub/Prefix.pdf */
for (i = 0; i < srclen; ++i) { for (i = 0; i < srclen; ++i) {
uint8_t in = src[i] >> 4; const nghttp2_huff_decode *t;
for (j = 0; j < 2; ++j) {
const nghttp2_huff_decode *t;
t = &huff_decode_table[ctx->state][in]; t = &huff_decode_table[ctx->state][src[i] >> 4];
if (t->flags & NGHTTP2_HUFF_FAIL) { if (t->flags & NGHTTP2_HUFF_FAIL) {
return NGHTTP2_ERR_HEADER_COMP; return NGHTTP2_ERR_HEADER_COMP;
}
if (t->flags & NGHTTP2_HUFF_SYM) {
if (avail) {
nghttp2_bufs_fast_addb(bufs, t->sym);
--avail;
} else {
rv = nghttp2_bufs_addb(bufs, t->sym);
if (rv != 0) {
return rv;
}
avail = nghttp2_bufs_cur_avail(bufs);
}
}
ctx->state = t->state;
ctx->accept = (t->flags & NGHTTP2_HUFF_ACCEPTED) != 0;
in = src[i] & 0xf;
} }
if (t->flags & NGHTTP2_HUFF_SYM) {
/* this is macro, and may return from this function on error */
hd_huff_decode_sym_emit(bufs, t->sym, avail);
}
t = &huff_decode_table[t->state][src[i] & 0xf];
if (t->flags & NGHTTP2_HUFF_FAIL) {
return NGHTTP2_ERR_HEADER_COMP;
}
if (t->flags & NGHTTP2_HUFF_SYM) {
/* this is macro, and may return from this function on error */
hd_huff_decode_sym_emit(bufs, t->sym, avail);
}
ctx->state = t->state;
ctx->accept = (t->flags & NGHTTP2_HUFF_ACCEPTED) != 0;
} }
if (final && !ctx->accept) { if (final && !ctx->accept) {
return NGHTTP2_ERR_HEADER_COMP; return NGHTTP2_ERR_HEADER_COMP;