From f8bd028dc0a99afeed68e6c3bf28ce6faf3012e2 Mon Sep 17 00:00:00 2001 From: Glenn Strauss Date: Tue, 25 May 2021 05:04:36 -0400 Subject: [PATCH] [core] http_header_hkey_get() perf (better asm) --- src/http_header.c | 48 +++++++++++++++++++++++++++++++---------------- src/http_header.h | 4 ++-- 2 files changed, 34 insertions(+), 18 deletions(-) diff --git a/src/http_header.c b/src/http_header.c index 66609372..dc20e0c0 100644 --- a/src/http_header.c +++ b/src/http_header.c @@ -94,25 +94,41 @@ static const keyvlenvalue http_headers[] = { ,{ HTTP_HEADER_OTHER, 0, "" } }; -enum http_header_e http_header_hkey_get(const char * const s, const uint32_t slen) { - const struct keyvlenvalue * const kv = http_headers; - int i = slen < sizeof(http_headers_off) ? http_headers_off[slen] : -1; - if (i < 0) return HTTP_HEADER_OTHER; - do { - if (buffer_eq_icase_ssn(s, kv[i].value, slen)) - return (enum http_header_e)kv[i].key; - } while (slen == kv[++i].vlen); +enum http_header_e http_header_hkey_get(const char * const s, const size_t slen) { + if (__builtin_expect( (slen < sizeof(http_headers_off)), 1)) { + const int i = http_headers_off[slen]; + /*(lowercase first char as all recognized headers start w/ alpha char)*/ + const int c = s[0] | 0x20; + const struct keyvlenvalue * restrict kv = http_headers + i; + if (__builtin_expect( (i != -1), 1)) { + do { + if (__builtin_expect( (c != kv->value[0]), 1)) + continue; + if (buffer_eq_icase_ssn(s+1, kv->value+1, slen-1)) + return (enum http_header_e)kv->key; + } while (slen == (++kv)->vlen); + } + } return HTTP_HEADER_OTHER; } -enum http_header_e http_header_hkey_get_lc(const char * const s, const uint32_t slen) { - const struct keyvlenvalue * const kv = http_headers; - int i = slen < sizeof(http_headers_off) ? http_headers_off[slen] : -1; - if (i < 0) return HTTP_HEADER_OTHER; - do { - if (0 == memcmp(s, kv[i].value, slen)) - return (enum http_header_e)kv[i].key; - } while (slen == kv[++i].vlen); +enum http_header_e http_header_hkey_get_lc(const char * const s, const size_t slen) { + /* XXX: might not provide much real performance over http_header_hkey_get() + * (since the first-char comparision optimization was added) + * (and since well-known h2 headers are already mapped to hkey) */ + if (__builtin_expect( (slen < sizeof(http_headers_off)), 1)) { + const int i = http_headers_off[slen]; + const int c = s[0]; + const struct keyvlenvalue * restrict kv = http_headers + i; + if (__builtin_expect( (i != -1), 1)) { + do { + if (__builtin_expect( (c != kv->value[0]), 1)) + continue; + if (0 == memcmp(s+1, kv->value+1, slen-1)) + return (enum http_header_e)kv->key; + } while (slen == (++kv)->vlen); + } + } return HTTP_HEADER_OTHER; } diff --git a/src/http_header.h b/src/http_header.h index 0ff5fb46..13731468 100644 --- a/src/http_header.h +++ b/src/http_header.h @@ -88,9 +88,9 @@ enum http_header_e { }; __attribute_pure__ -enum http_header_e http_header_hkey_get(const char *s, uint32_t slen); +enum http_header_e http_header_hkey_get(const char *s, size_t slen); __attribute_pure__ -enum http_header_e http_header_hkey_get_lc(const char *s, uint32_t slen); +enum http_header_e http_header_hkey_get_lc(const char *s, size_t slen); __attribute_pure__ int http_header_str_to_code (const char * const s);