strmap: enable allocations to come from a mem_pool

For heavy users of strmaps, allowing the keys and entries to be allocated from a memory pool can provide significant overhead savings. Add an option to strmap_init_with_options() to specify a memory pool. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Elijah Newren committed Nov 11, 2020 at 20:02 UTC a208ec1f0b654390ad06372c53b7ffe785052d98
2 files changed +30 -12
strmap.c
+22 -9
@@ -1,5 +1,6 @@
1 #include "git-compat-util.h"
2 #include "strmap.h"
3 +#include "mem-pool.h"
4
5 int cmp_strmap_entry(const void *hashmap_cmp_fn_data,
6 const struct hashmap_entry *entry1,
@@ -24,13 +25,15 @@ static struct strmap_entry *find_strmap_entry(struct strmap *map,
25
26 void strmap_init(struct strmap *map)
27 {
27 - strmap_init_with_options(map, 1);
28 + strmap_init_with_options(map, NULL, 1);
29 }
30
31 void strmap_init_with_options(struct strmap *map,
32 + struct mem_pool *pool,
33 int strdup_strings)
34 {
35 hashmap_init(&map->map, cmp_strmap_entry, NULL, 0);
36 + map->pool = pool;
37 map->strdup_strings = strdup_strings;
38 }
39
@@ -42,6 +45,10 @@ static void strmap_free_entries_(struct strmap *map, int free_values)
45 if (!map)
46 return;
47
48 + if (!free_values && map->pool)
49 + /* Memory other than util is owned by and freed with the pool */
50 + return;
51 +
52 /*
53 * We need to iterate over the hashmap entries and free
54 * e->key and e->value ourselves; hashmap has no API to
@@ -52,9 +59,11 @@ static void strmap_free_entries_(struct strmap *map, int free_values)
59 hashmap_for_each_entry(&map->map, &iter, e, ent) {
60 if (free_values)
61 free(e->value);
55 - if (map->strdup_strings)
56 - free((char*)e->key);
57 - free(e);
62 + if (!map->pool) {
63 + if (map->strdup_strings)
64 + free((char*)e->key);
65 + free(e);
66 + }
67 }
68 }
69
@@ -77,11 +86,13 @@ static struct strmap_entry *create_entry(struct strmap *map,
86 struct strmap_entry *entry;
87 const char *key = str;
88
80 - entry = xmalloc(sizeof(*entry));
89 + entry = map->pool ? mem_pool_alloc(map->pool, sizeof(*entry))
90 + : xmalloc(sizeof(*entry));
91 hashmap_entry_init(&entry->ent, strhash(str));
92
93 if (map->strdup_strings)
84 - key = xstrdup(str);
94 + key = map->pool ? mem_pool_strdup(map->pool, str)
95 + : xstrdup(str);
96 entry->key = key;
97 entry->value = data;
98 return entry;
@@ -128,9 +139,11 @@ void strmap_remove(struct strmap *map, const char *str, int free_value)
139 return;
140 if (free_value)
141 free(ret->value);
131 - if (map->strdup_strings)
132 - free((char*)ret->key);
133 - free(ret);
142 + if (!map->pool) {
143 + if (map->strdup_strings)
144 + free((char*)ret->key);
145 + free(ret);
146 + }
147 }
148
149 void strintmap_incr(struct strintmap *map, const char *str, intptr_t amt)
strmap.h
+8 -3
@@ -3,8 +3,10 @@
3
4 #include "hashmap.h"
5
6 +struct mem_pool;
7 struct strmap {
8 struct hashmap map;
9 + struct mem_pool *pool;
10 unsigned int strdup_strings:1;
11 };
12
@@ -37,9 +39,10 @@ void strmap_init(struct strmap *map);
39
40 /*
41 * Same as strmap_init, but for those who want to control the memory management
40 - * carefully instead of using the default of strdup_strings=1.
42 + * carefully instead of using the default of strdup_strings=1 and pool=NULL.
43 */
44 void strmap_init_with_options(struct strmap *map,
45 + struct mem_pool *pool,
46 int strdup_strings);
47
48 /*
@@ -137,9 +140,10 @@ static inline void strintmap_init(struct strintmap *map, int default_value)
140
141 static inline void strintmap_init_with_options(struct strintmap *map,
142 int default_value,
143 + struct mem_pool *pool,
144 int strdup_strings)
145 {
142 - strmap_init_with_options(&map->map, strdup_strings);
146 + strmap_init_with_options(&map->map, pool, strdup_strings);
147 map->default_value = default_value;
148 }
149
@@ -221,9 +225,10 @@ static inline void strset_init(struct strset *set)
225 }
226
227 static inline void strset_init_with_options(struct strset *set,
228 + struct mem_pool *pool,
229 int strdup_strings)
230 {
226 - strmap_init_with_options(&set->map, strdup_strings);
231 + strmap_init_with_options(&set->map, pool, strdup_strings);
232 }
233
234 static inline void strset_clear(struct strset *set)