From 52dbaef6da882be427412fda02a3dc7606fdea26 Mon Sep 17 00:00:00 2001 From: Justin Azoff Date: Mon, 18 Feb 2019 12:50:22 -0500 Subject: [PATCH] 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. --- src/Dict.cc | 27 +++++++++++++++++++++++---- src/List.cc | 37 +++++++++++++------------------------ src/List.h | 4 +--- 3 files changed, 37 insertions(+), 31 deletions(-) diff --git a/src/Dict.cc b/src/Dict.cc index 9e68d64089..abcc1a78c8 100644 --- a/src/Dict.cc +++ b/src/Dict.cc @@ -53,7 +53,7 @@ public: Dictionary::Dictionary(dict_order ordering, int initial_size) { - Init(initial_size); + tbl = 0; tbl2 = 0; if ( ordering == ORDERED ) @@ -61,14 +61,13 @@ Dictionary::Dictionary(dict_order ordering, int initial_size) else order = 0; - SetDensityThresh(DEFAULT_DENSITY_THRESH); - delete_func = 0; tbl_next_ind = 0; cumulative_entries = 0; num_buckets2 = num_entries2 = max_num_entries2 = thresh_entries2 = 0; den_thresh2 = 0; + max_num_entries = num_entries = 0; } Dictionary::~Dictionary() @@ -80,12 +79,14 @@ Dictionary::~Dictionary() void Dictionary::Clear() { DeInit(); - Init(2); + tbl = 0; tbl2 = 0; } void Dictionary::DeInit() { + if ( tbl == 0 ) + return; for ( int i = 0; i < num_buckets; ++i ) if ( tbl[i] ) { @@ -127,6 +128,8 @@ void Dictionary::DeInit() void* Dictionary::Lookup(const void* key, int key_size, hash_t hash) const { + if (tbl == 0 && tbl2 == 0 ) + return 0; hash_t h; 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, int copy_key) { + if ( tbl == 0 ) + Init(DEFAULT_DICT_SIZE); DictEntry* new_entry = new DictEntry(key, key_size, hash, val); 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, bool dont_delete) { + if ( tbl == 0 && tbl2 == 0 ) + return 0; hash_t h; PList(DictEntry)* chain; 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 { + if ( tbl == 0 && tbl2 == 0 ) + { + const_cast(&cookies)->remove(cookie); + delete cookie; + cookie = 0; + return 0; + } // If there are any inserted entries, return them first. // That keeps the list small and helps avoiding searching // a large list when deleting an entry. @@ -366,6 +380,7 @@ void Dictionary::Init(int size) tbl[i] = 0; max_num_entries = num_entries = 0; + SetDensityThresh(DEFAULT_DENSITY_THRESH); } void Dictionary::Init2(int size) @@ -382,6 +397,8 @@ void Dictionary::Init2(int size) // private void* Dictionary::Insert(DictEntry* new_entry, int copy_key) { + if ( tbl == 0 ) + Init(DEFAULT_DICT_SIZE); PList(DictEntry)** ttbl; int* num_entries_ptr; int* max_num_entries_ptr; @@ -568,6 +585,8 @@ unsigned int Dictionary::MemoryAllocation() const { int size = padded_sizeof(*this); + if ( tbl == 0 ) + return size; for ( int i = 0; i < num_buckets; ++i ) if ( tbl[i] ) { diff --git a/src/List.cc b/src/List.cc index a2b4609975..23604a7d04 100644 --- a/src/List.cc +++ b/src/List.cc @@ -6,33 +6,27 @@ #include "List.h" #include "util.h" -static const int DEFAULT_CHUNK_SIZE = 10; +#define DEFAULT_LIST_SIZE 10 +#define GROWTH_FACTOR 2 BaseList::BaseList(int size) { - chunk_size = DEFAULT_CHUNK_SIZE; + num_entries = 0; + max_entries = 0; + entry = 0; - if ( size < 0 ) - { - num_entries = max_entries = 0; - entry = 0; - } - else - { - if ( size > 0 ) - chunk_size = size; + if ( size <= 0 ) + return; - num_entries = 0; - entry = (ent *) safe_malloc(chunk_size * sizeof(ent)); - max_entries = chunk_size; - } + max_entries = size; + + entry = (ent *) safe_malloc(max_entries * sizeof(ent)); } BaseList::BaseList(BaseList& b) { max_entries = b.max_entries; - chunk_size = b.chunk_size; num_entries = b.num_entries; if ( max_entries ) @@ -58,7 +52,6 @@ void BaseList::operator=(BaseList& b) free(entry); max_entries = b.max_entries; - chunk_size = b.chunk_size; num_entries = b.num_entries; if ( max_entries ) @@ -74,8 +67,7 @@ void BaseList::insert(ent a) { if ( num_entries == max_entries ) { - resize(max_entries + chunk_size); // make more room - chunk_size *= 2; + resize(max_entries==0 ? DEFAULT_LIST_SIZE : max_entries*GROWTH_FACTOR); // make more room } 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. if ( num_entries == max_entries ) { - resize(max_entries + chunk_size); - chunk_size *= 2; + resize(max_entries==0 ? DEFAULT_LIST_SIZE : max_entries*GROWTH_FACTOR); } entry[num_entries++] = a; @@ -142,8 +133,7 @@ void BaseList::append(ent a) { if ( num_entries == max_entries ) { - resize(max_entries + chunk_size); // make more room - chunk_size *= 2; + resize(max_entries==0 ? DEFAULT_LIST_SIZE : max_entries*GROWTH_FACTOR); // make more room } entry[num_entries++] = a; @@ -168,7 +158,6 @@ void BaseList::clear() } num_entries = max_entries = 0; - chunk_size = DEFAULT_CHUNK_SIZE; } ent BaseList::replace(int ent_index, ent new_ent) diff --git a/src/List.h b/src/List.h index fcc0274225..6fb2bbcec6 100644 --- a/src/List.h +++ b/src/List.h @@ -11,7 +11,7 @@ // element up, and resizing the list, which involves getting new space // and moving the data. Resizing occurs automatically when inserting // 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 // (or to less than the current value of num_entries) // will decrease the size of the list to the current number of @@ -32,7 +32,6 @@ public: void clear(); // remove all entries int length() const { return num_entries; } - int chunk() const { return chunk_size; } int max() const { return max_entries; } int resize(int = 0); // 0 => size to fit current number of entries @@ -79,7 +78,6 @@ protected: void operator=(BaseList&); ent* entry; - int chunk_size; // increase size by this amount when necessary int max_entries; int num_entries; };