Loading src/common/container.c +22 −27 Original line number Diff line number Diff line Loading @@ -769,8 +769,6 @@ digestmap_set(digestmap_t *map, const char *key, void *val) { #ifndef OPTIMIZED_DIGESTMAP_SET digestmap_entry_t *resolve; #else digestmap_entry_t **resolve_ptr; #endif digestmap_entry_t search; void *oldval; Loading @@ -792,31 +790,28 @@ digestmap_set(digestmap_t *map, const char *key, void *val) return NULL; } #else /* XXXX020 We spend up to 5% of our time in this function, so the code * below is meant to optimize the check/alloc/set cycle by avoiding the * two trips to the hash table that we do in the unoptimized code above. * (Each of HT_INSERT and HT_FIND calls HT_SET_HASH and HT_FIND_P.) * * Unfortunately, doing this requires us to poke around inside hash-table * internals. It would be nice to avoid that. */ if (!map->head.hth_table || map->head.hth_n_entries >= map->head.hth_load_limit) digestmap_impl_HT_GROW((&map->head), map->head.hth_n_entries+1); _HT_SET_HASH(&search, node, digestmap_entry_hash); resolve_ptr = _digestmap_impl_HT_FIND_P(&map->head, &search); if (*resolve_ptr) { oldval = (*resolve_ptr)->val; (*resolve_ptr)->val = val; /* We spend up to 5% of our time in this function, so the code below is * meant to optimize the check/alloc/set cycle by avoiding the two trips to * the hash table that we do in the unoptimized code above. (Each of * HT_INSERT and HT_FIND calls HT_SET_HASH and HT_FIND_P.) */ _HT_FIND_OR_INSERT(digestmap_impl, node, digestmap_entry_hash, &(map->head), digestmap_entry_t, &search, ptr, { /* we found an entry. */ oldval = (*ptr)->val; (*ptr)->val = val; return oldval; } else { digestmap_entry_t *newent = tor_malloc_zero(sizeof(digestmap_entry_t)); }, { /* We didn't find the entry. */ digestmap_entry_t *newent = tor_malloc_zero(sizeof(digestmap_entry_t)); memcpy(newent->key, key, DIGEST_LEN); newent->val = val; newent->node.hte_hash = search.node.hte_hash; *resolve_ptr = newent; ++map->head.hth_n_entries; _HT_FOI_INSERT(node, &(map->head), &search, newent, ptr); return NULL; } }); #endif } Loading src/common/ht.h +25 −0 Original line number Diff line number Diff line Loading @@ -382,6 +382,31 @@ ht_string_hash(const char *s) return 0; \ } /** Implements an over-optimized "find and insert if absent" block; * not meant for direct usage by typical code, or usage outside the critical * path.*/ #define _HT_FIND_OR_INSERT(name, field, hashfn, head, eltype, elm, var, y, n) \ { \ struct name *_##var##_head = head; \ eltype **var; \ if (!_##var##_head->hth_table || \ _##var##_head->hth_n_entries >= _##var##_head->hth_load_limit) \ name##_HT_GROW(_##var##_head, _##var##_head->hth_n_entries+1); \ _HT_SET_HASH((elm), field, hashfn); \ var = _##name##_HT_FIND_P(_##var##_head, (elm)); \ if (*var) { \ y; \ } else { \ n; \ } \ } #define _HT_FOI_INSERT(field, head, elm, newent, var) \ { \ newent->field.hte_hash = (elm)->field.hte_hash; \ *var = newent; \ ++((head)->hth_n_entries); \ } /* * Copyright 2005, Nick Mathewson. Implementation logic is adapted from code * by Cristopher Clark, retrofit to allow drop-in memory management, and to Loading Loading
src/common/container.c +22 −27 Original line number Diff line number Diff line Loading @@ -769,8 +769,6 @@ digestmap_set(digestmap_t *map, const char *key, void *val) { #ifndef OPTIMIZED_DIGESTMAP_SET digestmap_entry_t *resolve; #else digestmap_entry_t **resolve_ptr; #endif digestmap_entry_t search; void *oldval; Loading @@ -792,31 +790,28 @@ digestmap_set(digestmap_t *map, const char *key, void *val) return NULL; } #else /* XXXX020 We spend up to 5% of our time in this function, so the code * below is meant to optimize the check/alloc/set cycle by avoiding the * two trips to the hash table that we do in the unoptimized code above. * (Each of HT_INSERT and HT_FIND calls HT_SET_HASH and HT_FIND_P.) * * Unfortunately, doing this requires us to poke around inside hash-table * internals. It would be nice to avoid that. */ if (!map->head.hth_table || map->head.hth_n_entries >= map->head.hth_load_limit) digestmap_impl_HT_GROW((&map->head), map->head.hth_n_entries+1); _HT_SET_HASH(&search, node, digestmap_entry_hash); resolve_ptr = _digestmap_impl_HT_FIND_P(&map->head, &search); if (*resolve_ptr) { oldval = (*resolve_ptr)->val; (*resolve_ptr)->val = val; /* We spend up to 5% of our time in this function, so the code below is * meant to optimize the check/alloc/set cycle by avoiding the two trips to * the hash table that we do in the unoptimized code above. (Each of * HT_INSERT and HT_FIND calls HT_SET_HASH and HT_FIND_P.) */ _HT_FIND_OR_INSERT(digestmap_impl, node, digestmap_entry_hash, &(map->head), digestmap_entry_t, &search, ptr, { /* we found an entry. */ oldval = (*ptr)->val; (*ptr)->val = val; return oldval; } else { digestmap_entry_t *newent = tor_malloc_zero(sizeof(digestmap_entry_t)); }, { /* We didn't find the entry. */ digestmap_entry_t *newent = tor_malloc_zero(sizeof(digestmap_entry_t)); memcpy(newent->key, key, DIGEST_LEN); newent->val = val; newent->node.hte_hash = search.node.hte_hash; *resolve_ptr = newent; ++map->head.hth_n_entries; _HT_FOI_INSERT(node, &(map->head), &search, newent, ptr); return NULL; } }); #endif } Loading
src/common/ht.h +25 −0 Original line number Diff line number Diff line Loading @@ -382,6 +382,31 @@ ht_string_hash(const char *s) return 0; \ } /** Implements an over-optimized "find and insert if absent" block; * not meant for direct usage by typical code, or usage outside the critical * path.*/ #define _HT_FIND_OR_INSERT(name, field, hashfn, head, eltype, elm, var, y, n) \ { \ struct name *_##var##_head = head; \ eltype **var; \ if (!_##var##_head->hth_table || \ _##var##_head->hth_n_entries >= _##var##_head->hth_load_limit) \ name##_HT_GROW(_##var##_head, _##var##_head->hth_n_entries+1); \ _HT_SET_HASH((elm), field, hashfn); \ var = _##name##_HT_FIND_P(_##var##_head, (elm)); \ if (*var) { \ y; \ } else { \ n; \ } \ } #define _HT_FOI_INSERT(field, head, elm, newent, var) \ { \ newent->field.hte_hash = (elm)->field.hte_hash; \ *var = newent; \ ++((head)->hth_n_entries); \ } /* * Copyright 2005, Nick Mathewson. Implementation logic is adapted from code * by Cristopher Clark, retrofit to allow drop-in memory management, and to Loading