Skip to content

Commit

Permalink
OPTIM: vars: use multiple name heads in the vars struct
Browse files Browse the repository at this point in the history
Given that the original list-based version was using a list head as the
root of the variables, while the tree is using a single pointer, it made
sense to reuse that space to place multiple roots, indexed on the lower
bits of the name hash. Two roots slightly increase the performance level,
but the best gain is obtained with 4 roots. The performance is now always
above that of the list, even with small counts, and with 100 vars, it's
21% higher than before, or 67% higher than with the list.

We keep the same lock (it could have made sense to use one lock per head),
because most of the variables in large configs are attached to a stream
or a session, hence are not shared between threads. Thus there's no point
in sharding the pointer.
  • Loading branch information
wtarreau committed Sep 15, 2024
1 parent 47ec7c6 commit 5d350d1
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 11 deletions.
3 changes: 2 additions & 1 deletion include/haproxy/vars-t.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,9 @@ enum vars_scope {
SCOPE_CHECK,
};

#define VAR_NAME_ROOTS 4
struct vars {
struct ceb_node *name_root;
struct ceb_node *name_root[VAR_NAME_ROOTS];
enum vars_scope scope;
unsigned int size;
__decl_thread(HA_RWLOCK_T rwlock);
Expand Down
9 changes: 6 additions & 3 deletions include/haproxy/vars.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,13 @@ static inline void vars_prune(struct vars *vars, struct session *sess, struct st
struct ceb_node *node;
struct var *var;
unsigned int size = 0;
int i;

while ((node = cebu64_first(&vars->name_root))) {
var = container_of(node, struct var, node);
size += var_clear(vars, var, 1);
for (i = 0; i < VAR_NAME_ROOTS; i++) {
while ((node = cebu64_first(&vars->name_root[i]))) {
var = container_of(node, struct var, node);
size += var_clear(vars, var, 1);
}
}

if (!size)
Expand Down
17 changes: 10 additions & 7 deletions src/vars.c
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ unsigned int var_clear(struct vars *vars, struct var *var, int force)
var->data.type = SMP_T_ANY;

if (!(var->flags & VF_PERMANENT) || force) {
cebu64_delete(&vars->name_root, &var->node);
cebu64_delete(&vars->name_root[var->name_hash % VAR_NAME_ROOTS], &var->node);
pool_free(var_pool, var);
size += sizeof(struct var);
}
Expand All @@ -205,10 +205,13 @@ void vars_prune_per_sess(struct vars *vars)
struct ceb_node *node;
struct var *var;
unsigned int size = 0;
int i;

while ((node = cebu64_first(&vars->name_root))) {
var = container_of(node, struct var, node);
size += var_clear(vars, var, 1);
for (i = 0; i < VAR_NAME_ROOTS; i++) {
while ((node = cebu64_first(&vars->name_root[i]))) {
var = container_of(node, struct var, node);
size += var_clear(vars, var, 1);
}
}

if (!size)
Expand All @@ -223,7 +226,7 @@ void vars_prune_per_sess(struct vars *vars)
/* This function initializes a variables list head */
void vars_init_head(struct vars *vars, enum vars_scope scope)
{
vars->name_root = NULL;
memset(vars->name_root, 0, sizeof(vars->name_root));
vars->scope = scope;
vars->size = 0;
HA_RWLOCK_INIT(&vars->rwlock);
Expand Down Expand Up @@ -333,7 +336,7 @@ static struct var *var_get(struct vars *vars, uint64_t name_hash)
{
struct ceb_node *node;

node = cebu64_lookup(&vars->name_root, name_hash);
node = cebu64_lookup(&vars->name_root[name_hash % VAR_NAME_ROOTS], name_hash);
if (node)
return container_of(node, struct var, node);

Expand Down Expand Up @@ -436,7 +439,7 @@ int var_set(const struct var_desc *desc, struct sample *smp, uint flags)
var->name_hash = desc->name_hash;
var->flags = flags & VF_PERMANENT;
var->data.type = SMP_T_ANY;
cebu64_insert(&vars->name_root, &var->node);
cebu64_insert(&vars->name_root[var->name_hash % VAR_NAME_ROOTS], &var->node);
}

/* A variable of type SMP_T_ANY is considered as unset (either created
Expand Down

0 comments on commit 5d350d1

Please sign in to comment.