Dict: Reduce some math required in repeatedly-called functions

This commit is contained in:
Tim Wojtulewicz 2022-08-31 20:48:18 +00:00 committed by Tim Wojtulewicz
parent 25a280d6a1
commit 1befb9ba6f

View file

@ -457,7 +457,7 @@ public:
{ {
// If an initial size is speicified, init the table right away. Otherwise wait until the // If an initial size is speicified, init the table right away. Otherwise wait until the
// first insertion to init. // first insertion to init.
log2_buckets = static_cast<unsigned char>(std::log2(initial_size)); SetLog2Buckets(static_cast<uint16_t>(std::log2(initial_size)));
Init(); Init();
} }
@ -727,13 +727,8 @@ public:
} }
/// The capacity of the table, Buckets + Overflow Size. /// The capacity of the table, Buckets + Overflow Size.
int Capacity(bool expected = false) const int Capacity() const { return table ? bucket_capacity : 0; }
{ int ExpectedCapacity() const { return bucket_capacity; }
int capacity = (1 << log2_buckets) + (log2_buckets + 0);
if ( expected )
return capacity;
return table ? capacity : 0;
}
// Debugging // Debugging
#define DUMPIF(f) \ #define DUMPIF(f) \
@ -932,17 +927,18 @@ private:
friend zeek::DictIterator<T>; friend zeek::DictIterator<T>;
friend zeek::RobustDictIterator<T>; friend zeek::RobustDictIterator<T>;
/// Buckets of the table, not including overflow size. void SetLog2Buckets(int value)
int Buckets(bool expected = false) const
{ {
int buckets = (1 << log2_buckets); log2_buckets = value;
if ( expected ) bucket_count = 1 << log2_buckets;
return buckets; bucket_capacity = (1 << log2_buckets) + log2_buckets;
return table ? buckets : 0;
} }
/// Buckets of the table, not including overflow size.
int Buckets() const { return table ? bucket_count : 0; }
// bucket math // bucket math
int ThresholdEntries() const uint32_t ThresholdEntries() const
{ {
// Increase the size of the dictionary when it is 75% full. However, when the dictionary // Increase the size of the dictionary when it is 75% full. However, when the dictionary
// is small ( <= 20 elements ), only resize it when it's 100% full. The dictionary will // is small ( <= 20 elements ), only resize it when it's 100% full. The dictionary will
@ -998,7 +994,8 @@ private:
{ {
ASSERT(bucket >= 0 && bucket < Buckets()); ASSERT(bucket >= 0 && bucket < Buckets());
int i = bucket; int i = bucket;
while ( i < Capacity() && ! table[i].Empty() && BucketByPosition(i) <= bucket ) int current_cap = Capacity();
while ( i < current_cap && ! table[i].Empty() && BucketByPosition(i) <= bucket )
i++; i++;
return i; return i;
} }
@ -1025,7 +1022,8 @@ private:
int bucket = BucketByPosition(position); int bucket = BucketByPosition(position);
int i = position; int i = position;
while ( i < Capacity() && ! table[i].Empty() && BucketByPosition(i) == bucket ) int current_cap = Capacity();
while ( i < current_cap && ! table[i].Empty() && BucketByPosition(i) == bucket )
i++; // stop just over the tail. i++; // stop just over the tail.
return i - 1; return i - 1;
@ -1050,10 +1048,11 @@ private:
{ {
ASSERT(table && -1 <= position && position < Capacity()); ASSERT(table && -1 <= position && position < Capacity());
int current_cap = Capacity();
do do
{ {
position++; position++;
} while ( position < Capacity() && table[position].Empty() ); } while ( position < current_cap && table[position].Empty() );
return position; return position;
} }
@ -1061,7 +1060,7 @@ private:
void Init() void Init()
{ {
ASSERT(! table); ASSERT(! table);
table = (detail::DictEntry<T>*)malloc(sizeof(detail::DictEntry<T>) * Capacity(true)); table = (detail::DictEntry<T>*)malloc(sizeof(detail::DictEntry<T>) * ExpectedCapacity());
for ( int i = Capacity() - 1; i >= 0; i-- ) for ( int i = Capacity() - 1; i >= 0; i-- )
table[i].SetEmpty(); table[i].SetEmpty();
} }
@ -1069,7 +1068,8 @@ private:
// Lookup // Lookup
int LinearLookupIndex(const void* key, int key_size, detail::hash_t hash) const int LinearLookupIndex(const void* key, int key_size, detail::hash_t hash) const
{ {
for ( int i = 0; i < Capacity(); i++ ) auto current_cap = Capacity();
for ( int i = 0; i < current_cap; i++ )
if ( ! table[i].Empty() && table[i].Equal((const char*)key, key_size, hash) ) if ( ! table[i].Empty() && table[i].Equal((const char*)key, key_size, hash) )
return i; return i;
return -1; return -1;
@ -1381,7 +1381,8 @@ private:
void SizeUp() void SizeUp()
{ {
int prev_capacity = Capacity(); int prev_capacity = Capacity();
log2_buckets++; SetLog2Buckets(log2_buckets + 1);
int capacity = Capacity(); int capacity = Capacity();
table = (detail::DictEntry<T>*)realloc(table, capacity * sizeof(detail::DictEntry<T>)); table = (detail::DictEntry<T>*)realloc(table, capacity * sizeof(detail::DictEntry<T>));
for ( int i = prev_capacity; i < capacity; i++ ) for ( int i = prev_capacity; i < capacity; i++ )
@ -1488,18 +1489,20 @@ private:
// as it will be remapped to new dict size anyway. however, the missed count is recorded // as it will be remapped to new dict size anyway. however, the missed count is recorded
// for lookup. if position not found for a key in the position of dict of current size, it // for lookup. if position not found for a key in the position of dict of current size, it
// still could be in the position of dict of previous N sizes. // still could be in the position of dict of previous N sizes.
unsigned char remaps = 0; uint16_t remaps = 0;
unsigned char log2_buckets = 0; uint16_t log2_buckets = 0;
uint32_t bucket_capacity = 1;
uint32_t bucket_count = 1;
// Pending number of iterators on the Dict, including both robust and non-robust. // Pending number of iterators on the Dict, including both robust and non-robust.
// This is used to avoid remapping if there are any active iterators. // This is used to avoid remapping if there are any active iterators.
unsigned short num_iterators = 0; uint16_t num_iterators = 0;
// The last index to be remapped. // The last index to be remapped.
int remap_end = -1; int32_t remap_end = -1;
int num_entries = 0; uint32_t num_entries = 0;
int max_entries = 0; uint32_t max_entries = 0;
uint64_t cum_entries = 0; uint64_t cum_entries = 0;
dict_delete_func delete_func = nullptr; dict_delete_func delete_func = nullptr;