r13873@Kushana: nickm | 2007-07-31 10:54:05 -0700

Split over-optimized digestmap_set code into a generic part and a digestmap-specific part.


svn:r11012
This commit is contained in:
Nick Mathewson 2007-08-01 15:57:48 +00:00
parent 484c8b776d
commit d5c78593d2
2 changed files with 47 additions and 27 deletions

View File

@ -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;
@ -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;
return oldval;
} else {
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;
return NULL;
}
/* 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;
},
{
/* 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;
_HT_FOI_INSERT(node, &(map->head), &search, newent, ptr);
return NULL;
});
#endif
}

View File

@ -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