mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-03-11 05:48:41 +00:00
OPTIM: connection: progressive hash for conn_calculate_hash()
Some CPU time is needlessly wasted in conn_calculate_hash(), because all params are first copied into a temporary buffer before computing the hash on the whole buffer. Instead, let's leverage the XXH progressive hash update functions to avoid expensive memcpys.
This commit is contained in:
parent
1de149fb6d
commit
ea09075f59
@ -96,12 +96,6 @@ void sockaddr_free(struct sockaddr_storage **sap);
|
||||
/* connection hash stuff */
|
||||
uint64_t conn_calculate_hash(const struct conn_hash_params *params);
|
||||
uint64_t conn_hash_prehash(char *buf, size_t size);
|
||||
void conn_hash_update(char *buf, size_t *idx,
|
||||
const void *data, size_t size,
|
||||
enum conn_hash_params_t *flags,
|
||||
enum conn_hash_params_t type);
|
||||
uint64_t conn_hash_digest(char *buf, size_t bufsize,
|
||||
enum conn_hash_params_t flags);
|
||||
|
||||
int conn_reverse(struct connection *conn);
|
||||
|
||||
|
@ -2544,9 +2544,38 @@ static struct cfg_kw_list cfg_kws = {ILH, {
|
||||
|
||||
INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);
|
||||
|
||||
/* Generate the hash of a connection with params as input
|
||||
* Each non-null field of params is taken into account for the hash calcul.
|
||||
*/
|
||||
uint64_t conn_hash_prehash(char *buf, size_t size)
|
||||
{
|
||||
return XXH64(buf, size, 0);
|
||||
}
|
||||
|
||||
/* Computes <data> hash into <hash>. In the same time, <flags>
|
||||
* are updated with <type> for the hash header.
|
||||
*/
|
||||
static void conn_hash_update(XXH64_state_t *hash,
|
||||
const void *data, size_t size,
|
||||
enum conn_hash_params_t *flags,
|
||||
enum conn_hash_params_t type)
|
||||
{
|
||||
XXH64_update(hash, data, size);
|
||||
*flags |= type;
|
||||
}
|
||||
|
||||
static uint64_t conn_hash_digest(XXH64_state_t *hash,
|
||||
enum conn_hash_params_t flags)
|
||||
{
|
||||
const uint64_t flags_u64 = (uint64_t)flags;
|
||||
const uint64_t f_hash = XXH64_digest(hash);
|
||||
|
||||
return (flags_u64 << CONN_HASH_PAYLOAD_LEN) | CONN_HASH_GET_PAYLOAD(f_hash);
|
||||
}
|
||||
|
||||
/* private function to handle sockaddr as input for connection hash */
|
||||
static void conn_calculate_hash_sockaddr(const struct sockaddr_storage *ss,
|
||||
char *buf, size_t *idx,
|
||||
XXH64_state_t *hash,
|
||||
enum conn_hash_params_t *hash_flags,
|
||||
enum conn_hash_params_t param_type_addr,
|
||||
enum conn_hash_params_t param_type_port)
|
||||
@ -2558,12 +2587,12 @@ static void conn_calculate_hash_sockaddr(const struct sockaddr_storage *ss,
|
||||
case AF_INET:
|
||||
addr = (struct sockaddr_in *)ss;
|
||||
|
||||
conn_hash_update(buf, idx,
|
||||
conn_hash_update(hash,
|
||||
&addr->sin_addr, sizeof(addr->sin_addr),
|
||||
hash_flags, param_type_addr);
|
||||
|
||||
if (addr->sin_port) {
|
||||
conn_hash_update(buf, idx,
|
||||
conn_hash_update(hash,
|
||||
&addr->sin_port, sizeof(addr->sin_port),
|
||||
hash_flags, param_type_port);
|
||||
}
|
||||
@ -2573,12 +2602,12 @@ static void conn_calculate_hash_sockaddr(const struct sockaddr_storage *ss,
|
||||
case AF_INET6:
|
||||
addr6 = (struct sockaddr_in6 *)ss;
|
||||
|
||||
conn_hash_update(buf, idx,
|
||||
conn_hash_update(hash,
|
||||
&addr6->sin6_addr, sizeof(addr6->sin6_addr),
|
||||
hash_flags, param_type_addr);
|
||||
|
||||
if (addr6->sin6_port) {
|
||||
conn_hash_update(buf, idx,
|
||||
conn_hash_update(hash,
|
||||
&addr6->sin6_port, sizeof(addr6->sin6_port),
|
||||
hash_flags, param_type_port);
|
||||
}
|
||||
@ -2587,76 +2616,42 @@ static void conn_calculate_hash_sockaddr(const struct sockaddr_storage *ss,
|
||||
}
|
||||
}
|
||||
|
||||
/* Generate the hash of a connection with params as input
|
||||
* Each non-null field of params is taken into account for the hash calcul.
|
||||
*/
|
||||
uint64_t conn_hash_prehash(char *buf, size_t size)
|
||||
{
|
||||
return XXH64(buf, size, 0);
|
||||
}
|
||||
|
||||
/* Append <data> into <buf> at <idx> offset in preparation for connection hash
|
||||
* calcul. <idx> is incremented beyond data <size>. In the same time, <flags>
|
||||
* are updated with <type> for the hash header.
|
||||
*/
|
||||
void conn_hash_update(char *buf, size_t *idx,
|
||||
const void *data, size_t size,
|
||||
enum conn_hash_params_t *flags,
|
||||
enum conn_hash_params_t type)
|
||||
{
|
||||
memcpy(&buf[*idx], data, size);
|
||||
*idx += size;
|
||||
*flags |= type;
|
||||
}
|
||||
|
||||
uint64_t conn_hash_digest(char *buf, size_t bufsize,
|
||||
enum conn_hash_params_t flags)
|
||||
{
|
||||
const uint64_t flags_u64 = (uint64_t)flags;
|
||||
const uint64_t hash = XXH64(buf, bufsize, 0);
|
||||
|
||||
return (flags_u64 << CONN_HASH_PAYLOAD_LEN) | CONN_HASH_GET_PAYLOAD(hash);
|
||||
}
|
||||
|
||||
uint64_t conn_calculate_hash(const struct conn_hash_params *params)
|
||||
{
|
||||
char *buf;
|
||||
size_t idx = 0;
|
||||
uint64_t hash = 0;
|
||||
enum conn_hash_params_t hash_flags = 0;
|
||||
XXH64_state_t hash;
|
||||
|
||||
buf = trash.area;
|
||||
XXH64_reset(&hash, 0);
|
||||
|
||||
conn_hash_update(buf, &idx, ¶ms->target, sizeof(params->target), &hash_flags, 0);
|
||||
conn_hash_update(&hash, ¶ms->target, sizeof(params->target), &hash_flags, 0);
|
||||
|
||||
if (params->sni_prehash) {
|
||||
conn_hash_update(buf, &idx,
|
||||
conn_hash_update(&hash,
|
||||
¶ms->sni_prehash, sizeof(params->sni_prehash),
|
||||
&hash_flags, CONN_HASH_PARAMS_TYPE_SNI);
|
||||
}
|
||||
|
||||
if (params->dst_addr) {
|
||||
conn_calculate_hash_sockaddr(params->dst_addr,
|
||||
buf, &idx, &hash_flags,
|
||||
&hash, &hash_flags,
|
||||
CONN_HASH_PARAMS_TYPE_DST_ADDR,
|
||||
CONN_HASH_PARAMS_TYPE_DST_PORT);
|
||||
}
|
||||
|
||||
if (params->src_addr) {
|
||||
conn_calculate_hash_sockaddr(params->src_addr,
|
||||
buf, &idx, &hash_flags,
|
||||
&hash, &hash_flags,
|
||||
CONN_HASH_PARAMS_TYPE_SRC_ADDR,
|
||||
CONN_HASH_PARAMS_TYPE_SRC_PORT);
|
||||
}
|
||||
|
||||
if (params->proxy_prehash) {
|
||||
conn_hash_update(buf, &idx,
|
||||
conn_hash_update(&hash,
|
||||
¶ms->proxy_prehash, sizeof(params->proxy_prehash),
|
||||
&hash_flags, CONN_HASH_PARAMS_TYPE_PROXY);
|
||||
}
|
||||
|
||||
hash = conn_hash_digest(buf, idx, hash_flags);
|
||||
return hash;
|
||||
return conn_hash_digest(&hash, hash_flags);
|
||||
}
|
||||
|
||||
/* Reverse a <conn> connection instance. This effectively moves the connection
|
||||
|
Loading…
Reference in New Issue
Block a user