Skip to content

Commit

Permalink
libcrun: use an hash map to lookup the key
Browse files Browse the repository at this point in the history
Use a hash map to speed up the lookup of the string map.

If the array is too small, use a binary search on the sorted array.

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
  • Loading branch information
giuseppe committed Feb 13, 2025
1 parent cec3269 commit 3fb05c0
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 7 deletions.
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ AC_CHECK_HEADERS([error.h linux/openat2.h stdatomic.h linux/ioprio.h])

AC_CHECK_TYPES([atomic_int], [], [], [[#include <stdatomic.h>]])

AC_CHECK_FUNCS(copy_file_range fgetxattr statx fgetpwent_r issetugid memfd_create)
AC_CHECK_FUNCS(hsearch_r copy_file_range fgetxattr statx fgetpwent_r issetugid memfd_create)

AC_ARG_ENABLE(crun,
AS_HELP_STRING([--enable-crun], [Include crun executable in installation (default: yes)]),
Expand Down
69 changes: 63 additions & 6 deletions src/libcrun/string_map.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#define _GNU_SOURCE

#include <config.h>
#include <stdlib.h>
#include <errno.h>
#include "string_map.h"
#include "utils.h"
Expand All @@ -35,23 +36,76 @@ struct string_map_s
{
size_t len;
struct kv_s *kvs;

#ifdef HAVE_HSEARCH_R
struct hsearch_data htab;
bool htab_initialized;
#endif

bool sorted;
};

static int
compare_kv (const void *a, const void *b)
{
return strcmp (((struct kv_s *) a)->key, ((struct kv_s *) b)->key);
}

const char *
find_string_map_value (string_map *map, const char *name)

{
size_t i;
struct kv_s *r, key;

if (map == NULL)
if (map == NULL || map->len == 0)
return NULL;

for (i = 0; i < map->len; i++)
#ifdef HAVE_HSEARCH_R
ENTRY e, *ep;

/* Do not bother with hash tables for small maps. */
if (map->len < 8)
goto fallback;

if (! map->htab_initialized)
{
if (strcmp (map->kvs[i].key, name) == 0)
return map->kvs[i].value;
size_t i;

if (hcreate_r (map->len, &map->htab) == 0)
goto fallback;

for (i = 0; i < map->len; i++)
{
e.key = (char *) map->kvs[i].key;
e.data = map->kvs[i].value;
if (hsearch_r (e, ENTER, &ep, &map->htab) == 0)
{
hdestroy_r (&map->htab);
goto fallback;
}
}
map->htab_initialized = true;
}
return NULL;

e.key = (char *) name;
if (hsearch_r (e, FIND, &ep, &map->htab) == 0)
return NULL;

return ep->data;

fallback:
#endif

if (! map->sorted)
{
qsort (map->kvs, map->len, sizeof (struct kv_s), compare_kv);
map->sorted = true;
}

key.key = (char *) name;

r = bsearch (&key, map->kvs, map->len, sizeof (struct kv_s), compare_kv);
return r ? r->value : NULL;
}

string_map *
Expand Down Expand Up @@ -92,6 +146,9 @@ free_string_map (string_map *map)
{
size_t i;

if (map->htab_initialized)
hdestroy_r (&map->htab);

for (i = 0; i < map->len; i++)
{
free (map->kvs[i].key);
Expand Down
5 changes: 5 additions & 0 deletions src/libcrun/string_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@
#define _GNU_SOURCE

#include <config.h>

#ifdef HAVE_HSEARCH_R
# include <search.h>
#endif

#include <ocispec/runtime_spec_schema_config_schema.h>
#include "error.h"

Expand Down

0 comments on commit 3fb05c0

Please sign in to comment.