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:
parent
484c8b776d
commit
d5c78593d2
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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…
Reference in New Issue