From 0529fd1dde97494f63c78584cd70910c959fea87 Mon Sep 17 00:00:00 2001 From: hippoz <10706925-hippoz@users.noreply.gitlab.com> Date: Sun, 22 Jan 2023 20:26:46 +0200 Subject: [PATCH] optimize name lookup --- server.c | 30 ++++++++++++++++++++++-------- server.h | 2 ++ 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/server.c b/server.c index 6a11171..b8f05c0 100644 --- a/server.c +++ b/server.c @@ -19,12 +19,12 @@ // https://en.wikipedia.org/wiki/Fowler-Noll-Vo_hash_function#FNV-1a_hash -uint64_t hashmap_hash(const char *bytes, size_t map_len) +static inline uint32_t hashmap_hash(const char *bytes, int map_len) { - uint64_t hash = 0xcbf29ce484222325; + uint32_t hash = 0x811c9dc5; while (*bytes++) { - hash *= 0x100000001b3; + hash *= 0x01000193; hash ^= *bytes; } @@ -105,6 +105,8 @@ Bus *bus_create(const char *socket_path) for (int i = 0; i < BUS_MAX_NAMES; i++) { s->names[i].client = NULL; s->names[i].name = NULL; + s->names[i].root_index = i; + s->names[i].chain_count = 0; } s->names_count = 0; s->clients_count = 0; @@ -139,11 +141,15 @@ int bus_client_add(Bus *s, int fd) return -1; } -int bus_name_find(Bus *s, char *name) +static inline int bus_name_find(Bus *s, char *name) { int bucket = hashmap_hash(name, BUS_MAX_NAMES); - for (int i = bucket; i < bucket + 12 && i < BUS_MAX_NAMES; i++) { + if (s->names[bucket].name && s->names[bucket].chain_count == 0) { + return bucket; + } + + for (int i = bucket + 1; i < bucket + 12 && i < BUS_MAX_NAMES; i++) { if (s->names[i].name && strcmp(s->names[i].name, name) == 0) { return i; } @@ -158,12 +164,12 @@ BusClient *bus_name_find_client(Bus *s, char *name) if (name_index < 0) { return NULL; } - - if (!s->names[name_index].client) { + + if (unlikely(!s->names[name_index].client)) { return NULL; } - if (s->names[name_index].client->state != BUS_CLIENT_STATE_READY) { + if (unlikely(s->names[name_index].client->state != BUS_CLIENT_STATE_READY)) { return NULL; } @@ -182,6 +188,10 @@ BusName *bus_name_add(Bus *s, char *name, BusClient *client) if (!s->names[i].client) { for (int j = 0; j < BUS_NAMES_PER_CLIENT; j++) { if (!client->owned_names[j]) { + if (i != bucket) { + s->names[bucket].chain_count++; + } + s->names[i].root_index = bucket; client->owned_names[j] = &s->names[i]; s->names[i].client = client; s->names[i].name = name; @@ -266,6 +276,9 @@ void bus_name_remove(Bus *s, BusName *name) name->client = NULL; s->names_count--; + if (&s->names[name->root_index] != name) { + s->names[name->root_index].chain_count--; + } } void bus_client_remove(Bus *s, BusClient *c) @@ -284,6 +297,7 @@ void bus_client_remove(Bus *s, BusClient *c) c->owned_names[j] = NULL; } + bus_name_remove(s, c->unique_name); c->unique_name = NULL; c->match_count = 0; c->fd = -1; diff --git a/server.h b/server.h index 5d6503d..1f700bf 100644 --- a/server.h +++ b/server.h @@ -33,6 +33,8 @@ enum { typedef struct bus_name { char *name; struct bus_client *client; + uint16_t chain_count; + uint16_t root_index; } BusName; typedef struct bus_client {