Merge pull request #33284 from yuwata/hwdb-optimize

hwdb: improve performance
This commit is contained in:
Luca Boccassi 2024-06-12 14:02:25 +01:00 committed by GitHub
commit aa6d1f16e8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 29 additions and 33 deletions

View file

@ -105,13 +105,16 @@ static void bubbleinsert(struct strbuf_node *node,
} }
/* add string, return the index/offset into the buffer */ /* add string, return the index/offset into the buffer */
ssize_t strbuf_add_string(struct strbuf *str, const char *s, size_t len) { ssize_t strbuf_add_string_full(struct strbuf *str, const char *s, size_t len) {
uint8_t c; uint8_t c;
char *buf_new;
struct strbuf_child_entry *child;
struct strbuf_node *node;
ssize_t off; ssize_t off;
assert(str);
assert(s || len == 0);
if (len == SIZE_MAX)
len = strlen(s);
if (!str->root) if (!str->root)
return -EINVAL; return -EINVAL;
@ -124,10 +127,8 @@ ssize_t strbuf_add_string(struct strbuf *str, const char *s, size_t len) {
} }
str->in_len += len; str->in_len += len;
node = str->root; struct strbuf_node *node = str->root;
for (size_t depth = 0; depth <= len; depth++) { for (size_t depth = 0; depth <= len; depth++) {
struct strbuf_child_entry search;
/* match against current node */ /* match against current node */
off = node->value_off + node->value_len - len; off = node->value_off + node->value_len - len;
if (depth == len || (node->value_len >= len && memcmp(str->buf + off, s, len) == 0)) { if (depth == len || (node->value_len >= len && memcmp(str->buf + off, s, len) == 0)) {
@ -139,7 +140,7 @@ ssize_t strbuf_add_string(struct strbuf *str, const char *s, size_t len) {
c = s[len - 1 - depth]; c = s[len - 1 - depth];
/* lookup child node */ /* lookup child node */
search.c = c; struct strbuf_child_entry *child, search = { .c = c };
child = typesafe_bsearch(&search, node->children, node->children_count, strbuf_children_cmp); child = typesafe_bsearch(&search, node->children, node->children_count, strbuf_children_cmp);
if (!child) if (!child)
break; break;
@ -147,10 +148,8 @@ ssize_t strbuf_add_string(struct strbuf *str, const char *s, size_t len) {
} }
/* add new string */ /* add new string */
buf_new = realloc(str->buf, str->len + len+1); if (!GREEDY_REALLOC(str->buf, str->len + len + 1))
if (!buf_new)
return -ENOMEM; return -ENOMEM;
str->buf = buf_new;
off = str->len; off = str->len;
memcpy(str->buf + off, s, len); memcpy(str->buf + off, s, len);
str->len += len; str->len += len;
@ -168,13 +167,11 @@ ssize_t strbuf_add_string(struct strbuf *str, const char *s, size_t len) {
}; };
/* extend array, add new entry, sort for bisection */ /* extend array, add new entry, sort for bisection */
child = reallocarray(node->children, node->children_count + 1, sizeof(struct strbuf_child_entry)); if (!GREEDY_REALLOC(node->children, node->children_count + 1))
if (!child)
return -ENOMEM; return -ENOMEM;
str->nodes_count++; str->nodes_count++;
node->children = child;
bubbleinsert(node, c, TAKE_PTR(node_child)); bubbleinsert(node, c, TAKE_PTR(node_child));
return off; return off;

View file

@ -33,7 +33,10 @@ struct strbuf_child_entry {
}; };
struct strbuf* strbuf_new(void); struct strbuf* strbuf_new(void);
ssize_t strbuf_add_string(struct strbuf *str, const char *s, size_t len); ssize_t strbuf_add_string_full(struct strbuf *str, const char *s, size_t len);
static inline ssize_t strbuf_add_string(struct strbuf *str, const char *s) {
return strbuf_add_string_full(str, s, SIZE_MAX);
}
void strbuf_complete(struct strbuf *str); void strbuf_complete(struct strbuf *str);
struct strbuf* strbuf_free(struct strbuf *str); struct strbuf* strbuf_free(struct strbuf *str);
DEFINE_TRIVIAL_CLEANUP_FUNC(struct strbuf*, strbuf_free); DEFINE_TRIVIAL_CLEANUP_FUNC(struct strbuf*, strbuf_free);

View file

@ -461,7 +461,7 @@ int catalog_update(const char* database, const char* root, const char* const* di
SD_ID128_FORMAT_VAL(i->id), SD_ID128_FORMAT_VAL(i->id),
isempty(i->language) ? "C" : i->language); isempty(i->language) ? "C" : i->language);
offset = strbuf_add_string(sb, payload, strlen(payload)); offset = strbuf_add_string(sb, payload);
if (offset < 0) if (offset < 0)
return log_oom(); return log_oom();

View file

@ -138,15 +138,15 @@ static int trie_node_add_value(struct trie *trie, struct trie_node *node,
ssize_t k, v, fn = 0; ssize_t k, v, fn = 0;
struct trie_value_entry *val; struct trie_value_entry *val;
k = strbuf_add_string(trie->strings, key, strlen(key)); k = strbuf_add_string(trie->strings, key);
if (k < 0) if (k < 0)
return k; return k;
v = strbuf_add_string(trie->strings, value, strlen(value)); v = strbuf_add_string(trie->strings, value);
if (v < 0) if (v < 0)
return v; return v;
if (!compat) { if (!compat) {
fn = strbuf_add_string(trie->strings, filename, strlen(filename)); fn = strbuf_add_string(trie->strings, filename);
if (fn < 0) if (fn < 0)
return fn; return fn;
} }
@ -224,7 +224,7 @@ static int trie_insert(struct trie *trie, struct trie_node *node, const char *se
if (!s) if (!s)
return -ENOMEM; return -ENOMEM;
off = strbuf_add_string(trie->strings, s, p); off = strbuf_add_string_full(trie->strings, s, p);
if (off < 0) if (off < 0)
return off; return off;
@ -254,7 +254,7 @@ static int trie_insert(struct trie *trie, struct trie_node *node, const char *se
if (!new_child) if (!new_child)
return -ENOMEM; return -ENOMEM;
off = strbuf_add_string(trie->strings, search + i+1, strlen(search + i+1)); off = strbuf_add_string(trie->strings, search + i+1);
if (off < 0) if (off < 0)
return off; return off;

View file

@ -8,10 +8,6 @@
#include "strv.h" #include "strv.h"
#include "tests.h" #include "tests.h"
static ssize_t add_string(struct strbuf *sb, const char *s) {
return strbuf_add_string(sb, s, strlen(s));
}
TEST(strbuf) { TEST(strbuf) {
_cleanup_(strbuf_freep) struct strbuf *sb = NULL; _cleanup_(strbuf_freep) struct strbuf *sb = NULL;
_cleanup_strv_free_ char **l = NULL; _cleanup_strv_free_ char **l = NULL;
@ -19,14 +15,14 @@ TEST(strbuf) {
sb = strbuf_new(); sb = strbuf_new();
a = add_string(sb, "waldo"); a = strbuf_add_string(sb, "waldo");
b = add_string(sb, "foo"); b = strbuf_add_string(sb, "foo");
c = add_string(sb, "bar"); c = strbuf_add_string(sb, "bar");
d = add_string(sb, "waldo"); /* duplicate */ d = strbuf_add_string(sb, "waldo"); /* duplicate */
e = add_string(sb, "aldo"); /* duplicate */ e = strbuf_add_string(sb, "aldo"); /* duplicate */
f = add_string(sb, "do"); /* duplicate */ f = strbuf_add_string(sb, "do"); /* duplicate */
g = add_string(sb, "waldorf"); /* not a duplicate: matches from tail */ g = strbuf_add_string(sb, "waldorf"); /* not a duplicate: matches from tail */
h = add_string(sb, ""); h = strbuf_add_string(sb, "");
/* check the content of the buffer directly */ /* check the content of the buffer directly */
l = strv_parse_nulstr(sb->buf, sb->len); l = strv_parse_nulstr(sb->buf, sb->len);