Defer initialization of lists and dicts until an item is added.

Instead of pre-allocating every list with space for 10 items, don't
initialize it at all until the first Insert.

Instead of pre-allocating every dictionary with 17 buckets,
don't initialize it at all until the first Insert.
This commit is contained in:
Justin Azoff 2019-02-18 12:50:22 -05:00
parent aff3f4b3fd
commit 52dbaef6da
3 changed files with 37 additions and 31 deletions

View file

@ -53,7 +53,7 @@ public:
Dictionary::Dictionary(dict_order ordering, int initial_size) Dictionary::Dictionary(dict_order ordering, int initial_size)
{ {
Init(initial_size); tbl = 0;
tbl2 = 0; tbl2 = 0;
if ( ordering == ORDERED ) if ( ordering == ORDERED )
@ -61,14 +61,13 @@ Dictionary::Dictionary(dict_order ordering, int initial_size)
else else
order = 0; order = 0;
SetDensityThresh(DEFAULT_DENSITY_THRESH);
delete_func = 0; delete_func = 0;
tbl_next_ind = 0; tbl_next_ind = 0;
cumulative_entries = 0; cumulative_entries = 0;
num_buckets2 = num_entries2 = max_num_entries2 = thresh_entries2 = 0; num_buckets2 = num_entries2 = max_num_entries2 = thresh_entries2 = 0;
den_thresh2 = 0; den_thresh2 = 0;
max_num_entries = num_entries = 0;
} }
Dictionary::~Dictionary() Dictionary::~Dictionary()
@ -80,12 +79,14 @@ Dictionary::~Dictionary()
void Dictionary::Clear() void Dictionary::Clear()
{ {
DeInit(); DeInit();
Init(2); tbl = 0;
tbl2 = 0; tbl2 = 0;
} }
void Dictionary::DeInit() void Dictionary::DeInit()
{ {
if ( tbl == 0 )
return;
for ( int i = 0; i < num_buckets; ++i ) for ( int i = 0; i < num_buckets; ++i )
if ( tbl[i] ) if ( tbl[i] )
{ {
@ -127,6 +128,8 @@ void Dictionary::DeInit()
void* Dictionary::Lookup(const void* key, int key_size, hash_t hash) const void* Dictionary::Lookup(const void* key, int key_size, hash_t hash) const
{ {
if (tbl == 0 && tbl2 == 0 )
return 0;
hash_t h; hash_t h;
PList(DictEntry)* chain; PList(DictEntry)* chain;
@ -155,6 +158,8 @@ void* Dictionary::Lookup(const void* key, int key_size, hash_t hash) const
void* Dictionary::Insert(void* key, int key_size, hash_t hash, void* val, void* Dictionary::Insert(void* key, int key_size, hash_t hash, void* val,
int copy_key) int copy_key)
{ {
if ( tbl == 0 )
Init(DEFAULT_DICT_SIZE);
DictEntry* new_entry = new DictEntry(key, key_size, hash, val); DictEntry* new_entry = new DictEntry(key, key_size, hash, val);
void* old_val = Insert(new_entry, copy_key); void* old_val = Insert(new_entry, copy_key);
@ -179,6 +184,8 @@ void* Dictionary::Insert(void* key, int key_size, hash_t hash, void* val,
void* Dictionary::Remove(const void* key, int key_size, hash_t hash, void* Dictionary::Remove(const void* key, int key_size, hash_t hash,
bool dont_delete) bool dont_delete)
{ {
if ( tbl == 0 && tbl2 == 0 )
return 0;
hash_t h; hash_t h;
PList(DictEntry)* chain; PList(DictEntry)* chain;
int* num_entries_ptr; int* num_entries_ptr;
@ -280,6 +287,13 @@ void Dictionary::StopIteration(IterCookie* cookie) const
void* Dictionary::NextEntry(HashKey*& h, IterCookie*& cookie, int return_hash) const void* Dictionary::NextEntry(HashKey*& h, IterCookie*& cookie, int return_hash) const
{ {
if ( tbl == 0 && tbl2 == 0 )
{
const_cast<PList(IterCookie)*>(&cookies)->remove(cookie);
delete cookie;
cookie = 0;
return 0;
}
// If there are any inserted entries, return them first. // If there are any inserted entries, return them first.
// That keeps the list small and helps avoiding searching // That keeps the list small and helps avoiding searching
// a large list when deleting an entry. // a large list when deleting an entry.
@ -366,6 +380,7 @@ void Dictionary::Init(int size)
tbl[i] = 0; tbl[i] = 0;
max_num_entries = num_entries = 0; max_num_entries = num_entries = 0;
SetDensityThresh(DEFAULT_DENSITY_THRESH);
} }
void Dictionary::Init2(int size) void Dictionary::Init2(int size)
@ -382,6 +397,8 @@ void Dictionary::Init2(int size)
// private // private
void* Dictionary::Insert(DictEntry* new_entry, int copy_key) void* Dictionary::Insert(DictEntry* new_entry, int copy_key)
{ {
if ( tbl == 0 )
Init(DEFAULT_DICT_SIZE);
PList(DictEntry)** ttbl; PList(DictEntry)** ttbl;
int* num_entries_ptr; int* num_entries_ptr;
int* max_num_entries_ptr; int* max_num_entries_ptr;
@ -568,6 +585,8 @@ unsigned int Dictionary::MemoryAllocation() const
{ {
int size = padded_sizeof(*this); int size = padded_sizeof(*this);
if ( tbl == 0 )
return size;
for ( int i = 0; i < num_buckets; ++i ) for ( int i = 0; i < num_buckets; ++i )
if ( tbl[i] ) if ( tbl[i] )
{ {

View file

@ -6,33 +6,27 @@
#include "List.h" #include "List.h"
#include "util.h" #include "util.h"
static const int DEFAULT_CHUNK_SIZE = 10; #define DEFAULT_LIST_SIZE 10
#define GROWTH_FACTOR 2
BaseList::BaseList(int size) BaseList::BaseList(int size)
{ {
chunk_size = DEFAULT_CHUNK_SIZE;
if ( size < 0 )
{
num_entries = max_entries = 0;
entry = 0;
}
else
{
if ( size > 0 )
chunk_size = size;
num_entries = 0; num_entries = 0;
entry = (ent *) safe_malloc(chunk_size * sizeof(ent)); max_entries = 0;
max_entries = chunk_size; entry = 0;
}
if ( size <= 0 )
return;
max_entries = size;
entry = (ent *) safe_malloc(max_entries * sizeof(ent));
} }
BaseList::BaseList(BaseList& b) BaseList::BaseList(BaseList& b)
{ {
max_entries = b.max_entries; max_entries = b.max_entries;
chunk_size = b.chunk_size;
num_entries = b.num_entries; num_entries = b.num_entries;
if ( max_entries ) if ( max_entries )
@ -58,7 +52,6 @@ void BaseList::operator=(BaseList& b)
free(entry); free(entry);
max_entries = b.max_entries; max_entries = b.max_entries;
chunk_size = b.chunk_size;
num_entries = b.num_entries; num_entries = b.num_entries;
if ( max_entries ) if ( max_entries )
@ -74,8 +67,7 @@ void BaseList::insert(ent a)
{ {
if ( num_entries == max_entries ) if ( num_entries == max_entries )
{ {
resize(max_entries + chunk_size); // make more room resize(max_entries==0 ? DEFAULT_LIST_SIZE : max_entries*GROWTH_FACTOR); // make more room
chunk_size *= 2;
} }
for ( int i = num_entries; i > 0; --i ) for ( int i = num_entries; i > 0; --i )
@ -95,8 +87,7 @@ void BaseList::sortedinsert(ent a, list_cmp_func cmp_func)
// First append element. // First append element.
if ( num_entries == max_entries ) if ( num_entries == max_entries )
{ {
resize(max_entries + chunk_size); resize(max_entries==0 ? DEFAULT_LIST_SIZE : max_entries*GROWTH_FACTOR);
chunk_size *= 2;
} }
entry[num_entries++] = a; entry[num_entries++] = a;
@ -142,8 +133,7 @@ void BaseList::append(ent a)
{ {
if ( num_entries == max_entries ) if ( num_entries == max_entries )
{ {
resize(max_entries + chunk_size); // make more room resize(max_entries==0 ? DEFAULT_LIST_SIZE : max_entries*GROWTH_FACTOR); // make more room
chunk_size *= 2;
} }
entry[num_entries++] = a; entry[num_entries++] = a;
@ -168,7 +158,6 @@ void BaseList::clear()
} }
num_entries = max_entries = 0; num_entries = max_entries = 0;
chunk_size = DEFAULT_CHUNK_SIZE;
} }
ent BaseList::replace(int ent_index, ent new_ent) ent BaseList::replace(int ent_index, ent new_ent)

View file

@ -11,7 +11,7 @@
// element up, and resizing the list, which involves getting new space // element up, and resizing the list, which involves getting new space
// and moving the data. Resizing occurs automatically when inserting // and moving the data. Resizing occurs automatically when inserting
// more elements than the list can currently hold. Automatic // more elements than the list can currently hold. Automatic
// resizing is done one "chunk_size" of elements at a time and // resizing is done by growing by GROWTH_FACTOR at a time and
// always increases the size of the list. Resizing to zero // always increases the size of the list. Resizing to zero
// (or to less than the current value of num_entries) // (or to less than the current value of num_entries)
// will decrease the size of the list to the current number of // will decrease the size of the list to the current number of
@ -32,7 +32,6 @@ public:
void clear(); // remove all entries void clear(); // remove all entries
int length() const { return num_entries; } int length() const { return num_entries; }
int chunk() const { return chunk_size; }
int max() const { return max_entries; } int max() const { return max_entries; }
int resize(int = 0); // 0 => size to fit current number of entries int resize(int = 0); // 0 => size to fit current number of entries
@ -79,7 +78,6 @@ protected:
void operator=(BaseList&); void operator=(BaseList&);
ent* entry; ent* entry;
int chunk_size; // increase size by this amount when necessary
int max_entries; int max_entries;
int num_entries; int num_entries;
}; };