From c3328a2f71aaeaa65fe752a4863d4f63ffa68a7a Mon Sep 17 00:00:00 2001 From: Sokolov Yura Date: Thu, 5 Jan 2012 13:49:04 +0400 Subject: [PATCH 1/5] st use function instead of macro --- st.c | 320 ++++++++++++++++++++++++++++++----------------------------- 1 file changed, 161 insertions(+), 159 deletions(-) diff --git a/st.c b/st.c index d95f551063e040..9f2432d81cf056 100644 --- a/st.c +++ b/st.c @@ -86,7 +86,7 @@ static void rehash(st_table *); Table of prime numbers 2^n+a, 2<=n<=30. */ static const unsigned int primes[] = { - 8 + 3, + ST_DEFAULT_INIT_TABLE_SIZE, 16 + 3, 32 + 5, 64 + 3, @@ -307,40 +307,48 @@ count_collision(const struct st_hash_type *type) #define FOUND_ENTRY #endif -#define FIND_ENTRY(table, ptr, hash_val, bin_pos) do {\ - (bin_pos) = (hash_val)%(table)->num_bins;\ - (ptr) = (table)->bins[(bin_pos)];\ - FOUND_ENTRY;\ - if (PTR_NOT_EQUAL((table), (ptr), (hash_val), key)) {\ - COLLISION;\ - while (PTR_NOT_EQUAL((table), (ptr)->next, (hash_val), key)) {\ - (ptr) = (ptr)->next;\ - }\ - (ptr) = (ptr)->next;\ - }\ -} while (0) +static st_table_entry * +find_entry(st_table *table, st_data_t key, st_index_t hash_val, st_index_t bin_pos) +{ + register st_table_entry *ptr = table->bins[bin_pos]; + FOUND_ENTRY; + if (PTR_NOT_EQUAL(table, ptr, hash_val, key)) { + COLLISION; + while (PTR_NOT_EQUAL(table, ptr->next, hash_val, key)) { + ptr = ptr->next; + } + ptr = ptr->next; + } + return ptr; +} + +static inline st_index_t +find_packed_index(st_table *table, st_data_t key) +{ + st_index_t i = 0; + while (i < table->num_entries && (st_data_t)table->bins[i*2] != key) i++; + return i; +} #define collision_check 0 int st_lookup(st_table *table, register st_data_t key, st_data_t *value) { - st_index_t hash_val, bin_pos; + st_index_t hash_val; register st_table_entry *ptr; if (table->entries_packed) { - st_index_t i; - for (i = 0; i < table->num_entries; i++) { - if ((st_data_t)table->bins[i*2] == key) { - if (value !=0) *value = (st_data_t)table->bins[i*2+1]; - return 1; - } - } + st_index_t i = find_packed_index(table, key); + if (i < table->num_entries) { + if (value != 0) *value = (st_data_t)table->bins[i*2+1]; + return 1; + } return 0; } hash_val = do_hash(key, table); - FIND_ENTRY(table, ptr, hash_val, bin_pos); + ptr = find_entry(table, key, hash_val, hash_val % table->num_bins); if (ptr == 0) { return 0; @@ -354,22 +362,20 @@ st_lookup(st_table *table, register st_data_t key, st_data_t *value) int st_get_key(st_table *table, register st_data_t key, st_data_t *result) { - st_index_t hash_val, bin_pos; + st_index_t hash_val; register st_table_entry *ptr; if (table->entries_packed) { - st_index_t i; - for (i = 0; i < table->num_entries; i++) { - if ((st_data_t)table->bins[i*2] == key) { - if (result !=0) *result = (st_data_t)table->bins[i*2]; - return 1; - } - } + st_index_t i = find_packed_index(table, key); + if (i < table->num_entries) { + if (result != 0) *result = (st_data_t)table->bins[i*2]; + return 1; + } return 0; } hash_val = do_hash(key, table); - FIND_ENTRY(table, ptr, hash_val, bin_pos); + ptr = find_entry(table, key, hash_val, hash_val % table->num_bins); if (ptr == 0) { return 0; @@ -387,32 +393,34 @@ st_get_key(st_table *table, register st_data_t key, st_data_t *result) ((st_index_t)((table)->num_entries+1) * 2 <= (table)->num_bins && \ (table)->num_entries+1 <= MAX_PACKED_NUMHASH) -#define ADD_DIRECT(table, key, value, hash_val, bin_pos)\ -do {\ - st_table_entry *entry;\ - if ((table)->num_entries > ST_DEFAULT_MAX_DENSITY * (table)->num_bins) {\ - rehash(table);\ - (bin_pos) = (hash_val) % (table)->num_bins;\ - }\ - \ - entry = alloc(st_table_entry);\ - \ - entry->hash = (hash_val);\ - entry->key = (key);\ - entry->record = (value);\ - entry->next = (table)->bins[(bin_pos)];\ - if ((table)->head != 0) {\ - entry->fore = 0;\ - (entry->back = (table)->tail)->fore = entry;\ - (table)->tail = entry;\ - }\ - else {\ - (table)->head = (table)->tail = entry;\ - entry->fore = entry->back = 0;\ - }\ - (table)->bins[(bin_pos)] = entry;\ - (table)->num_entries++;\ -} while (0) +static void +add_direct(st_table * table, st_data_t key, st_data_t value, + st_index_t hash_val, st_index_t bin_pos) +{ + st_table_entry *entry; + if (table->num_entries > ST_DEFAULT_MAX_DENSITY * table->num_bins) { + rehash(table); + bin_pos = hash_val % table->num_bins; + } + + entry = alloc(st_table_entry); + + entry->hash = hash_val; + entry->key = key; + entry->record = value; + entry->next = table->bins[bin_pos]; + if (table->head != 0) { + entry->fore = 0; + (entry->back = table->tail)->fore = entry; + table->tail = entry; + } + else { + table->head = table->tail = entry; + entry->fore = entry->back = 0; + } + table->bins[bin_pos] = entry; + table->num_entries++; +} static void unpack_entries(register st_table *table) @@ -432,6 +440,23 @@ unpack_entries(register st_table *table) *table = tmp_table; } +static int +add_packed_direct(st_table *table, st_data_t key, st_data_t value) +{ + int res = 1; + if (MORE_PACKABLE_P(table)) { + st_index_t i = table->num_entries++; + table->bins[i*2] = (struct st_table_entry*)key; + table->bins[i*2+1] = (struct st_table_entry*)value; + } + else { + unpack_entries(table); + res = 0; + } + return res; +} + + int st_insert(register st_table *table, register st_data_t key, st_data_t value) { @@ -439,29 +464,22 @@ st_insert(register st_table *table, register st_data_t key, st_data_t value) register st_table_entry *ptr; if (table->entries_packed) { - st_index_t i; - for (i = 0; i < table->num_entries; i++) { - if ((st_data_t)table->bins[i*2] == key) { - table->bins[i*2+1] = (struct st_table_entry*)value; - return 1; - } - } - if (MORE_PACKABLE_P(table)) { - i = table->num_entries++; - table->bins[i*2] = (struct st_table_entry*)key; - table->bins[i*2+1] = (struct st_table_entry*)value; - return 0; - } - else { - unpack_entries(table); + st_index_t i = find_packed_index(table, key); + if (i < table->num_entries) { + table->bins[i*2+1] = (struct st_table_entry*)value; + return 1; } + if (add_packed_direct(table, key, value)) { + return 0; + } } hash_val = do_hash(key, table); - FIND_ENTRY(table, ptr, hash_val, bin_pos); + bin_pos = hash_val % table->num_bins; + ptr = find_entry(table, key, hash_val, bin_pos); if (ptr == 0) { - ADD_DIRECT(table, key, value, hash_val, bin_pos); + add_direct(table, key, value, hash_val, bin_pos); return 0; } else { @@ -478,30 +496,23 @@ st_insert2(register st_table *table, register st_data_t key, st_data_t value, register st_table_entry *ptr; if (table->entries_packed) { - st_index_t i; - for (i = 0; i < table->num_entries; i++) { - if ((st_data_t)table->bins[i*2] == key) { - table->bins[i*2+1] = (struct st_table_entry*)value; - return 1; - } - } - if (MORE_PACKABLE_P(table)) { - i = table->num_entries++; - table->bins[i*2] = (struct st_table_entry*)key; - table->bins[i*2+1] = (struct st_table_entry*)value; - return 0; - } - else { - unpack_entries(table); + st_index_t i = find_packed_index(table, key); + if (i < table->num_entries) { + table->bins[i*2+1] = (struct st_table_entry*)value; + return 1; } + if (add_packed_direct(table, key, value)) { + return 0; + } } hash_val = do_hash(key, table); - FIND_ENTRY(table, ptr, hash_val, bin_pos); + bin_pos = hash_val % table->num_bins; + ptr = find_entry(table, key, hash_val, bin_pos); if (ptr == 0) { key = (*func)(key); - ADD_DIRECT(table, key, value, hash_val, bin_pos); + add_direct(table, key, value, hash_val, bin_pos); return 0; } else { @@ -516,21 +527,14 @@ st_add_direct(st_table *table, st_data_t key, st_data_t value) st_index_t hash_val, bin_pos; if (table->entries_packed) { - int i; - if (MORE_PACKABLE_P(table)) { - i = table->num_entries++; - table->bins[i*2] = (struct st_table_entry*)key; - table->bins[i*2+1] = (struct st_table_entry*)value; - return; - } - else { - unpack_entries(table); - } + if (add_packed_direct(table, key, value)) { + return; + } } hash_val = do_hash(key, table); bin_pos = hash_val % table->num_bins; - ADD_DIRECT(table, key, value, hash_val, bin_pos); + add_direct(table, key, value, hash_val, bin_pos); } static void @@ -605,21 +609,32 @@ st_copy(st_table *old_table) return new_table; } -#define REMOVE_ENTRY(table, ptr) do \ - { \ - if ((ptr)->fore == 0 && (ptr)->back == 0) { \ - (table)->head = 0; \ - (table)->tail = 0; \ - } \ - else { \ - st_table_entry *fore = (ptr)->fore, *back = (ptr)->back; \ - if (fore) fore->back = back; \ - if (back) back->fore = fore; \ - if ((ptr) == (table)->head) (table)->head = fore; \ - if ((ptr) == (table)->tail) (table)->tail = back; \ - } \ - (table)->num_entries--; \ - } while (0) +static inline void +remove_entry(st_table *table, st_table_entry *ptr) +{ + if (ptr->fore == 0 && ptr->back == 0) { + table->head = 0; + table->tail = 0; + } + else { + st_table_entry *fore = ptr->fore, *back = ptr->back; + if (fore) fore->back = back; + if (back) back->fore = fore; + if (ptr == table->head) table->head = fore; + if (ptr == table->tail) table->tail = back; + } + table->num_entries--; +} + +static inline void +remove_packed_entry(st_table *table, st_index_t pos) +{ + table->num_entries--; + if (pos < table->num_entries) { + memmove(&table->bins[pos*2], &table->bins[(pos+1)*2], + sizeof(struct st_table_entry*) * 2*(table->num_entries-pos)); + } +} int st_delete(register st_table *table, register st_data_t *key, st_data_t *value) @@ -629,15 +644,11 @@ st_delete(register st_table *table, register st_data_t *key, st_data_t *value) register st_table_entry *ptr; if (table->entries_packed) { - st_index_t i; - for (i = 0; i < table->num_entries; i++) { - if ((st_data_t)table->bins[i*2] == *key) { - if (value != 0) *value = (st_data_t)table->bins[i*2+1]; - table->num_entries--; - memmove(&table->bins[i*2], &table->bins[(i+1)*2], - sizeof(struct st_table_entry*) * 2*(table->num_entries-i)); - return 1; - } + st_index_t i = find_packed_index(table, *key); + if (i < table->num_entries) { + if (value != 0) *value = (st_data_t)table->bins[i*2+1]; + remove_packed_entry(table, i); + return 1; } if (value != 0) *value = 0; return 0; @@ -648,7 +659,7 @@ st_delete(register st_table *table, register st_data_t *key, st_data_t *value) for (prev = &table->bins[hash_val]; (ptr = *prev) != 0; prev = &ptr->next) { if (EQUAL(table, *key, ptr->key)) { *prev = ptr->next; - REMOVE_ENTRY(table, ptr); + remove_entry(table, ptr); if (value != 0) *value = ptr->record; *key = ptr->key; free(ptr); @@ -667,13 +678,11 @@ st_delete_safe(register st_table *table, register st_data_t *key, st_data_t *val register st_table_entry *ptr; if (table->entries_packed) { - st_index_t i; - for (i = 0; i < table->num_entries; i++) { - if ((st_data_t)table->bins[i*2] == *key) { - if (value != 0) *value = (st_data_t)table->bins[i*2+1]; - table->bins[i*2] = (void *)never; - return 1; - } + st_index_t i = find_packed_index(table, *key); + if (i < table->num_entries) { + if (value != 0) *value = (st_data_t)table->bins[i*2+1]; + table->bins[i*2] = (void *)never; + return 1; } if (value != 0) *value = 0; return 0; @@ -684,7 +693,7 @@ st_delete_safe(register st_table *table, register st_data_t *key, st_data_t *val for (; ptr != 0; ptr = ptr->next) { if ((ptr->key != never) && EQUAL(table, ptr->key, *key)) { - REMOVE_ENTRY(table, ptr); + remove_entry(table, ptr); *key = ptr->key; if (value != 0) *value = ptr->record; ptr->key = ptr->record = never; @@ -740,27 +749,24 @@ st_update(st_table *table, st_data_t key, int (*func)(st_data_t key, st_data_t * st_data_t value; if (table->entries_packed) { - st_index_t i; - for (i = 0; i < table->num_entries; i++) { - if ((st_data_t)table->bins[i*2] == key) { - value = (st_data_t)table->bins[i*2+1]; - switch ((*func)(key, &value, arg)) { - case ST_CONTINUE: - table->bins[i*2+1] = (struct st_table_entry*)value; - break; - case ST_DELETE: - table->num_entries--; - memmove(&table->bins[i*2], &table->bins[(i+1)*2], - sizeof(struct st_table_entry*) * 2 * (table->num_entries-i)); - } - return 1; + st_index_t i = find_packed_index(table, key); + if (i < table->num_entries) { + value = (st_data_t)table->bins[i*2+1]; + switch ((*func)(key, &value, arg)) { + case ST_CONTINUE: + table->bins[i*2+1] = (struct st_table_entry*)value; + break; + case ST_DELETE: + remove_packed_entry(table, i); } + return 1; } return 0; } hash_val = do_hash(key, table); - FIND_ENTRY(table, ptr, hash_val, bin_pos); + bin_pos = hash_val % table->num_bins; + ptr = find_entry(table, key, hash_val, bin_pos); if (ptr == 0) { return 0; @@ -777,7 +783,7 @@ st_update(st_table *table, st_data_t key, int (*func)(st_data_t key, st_data_t * if (ptr == tmp) { tmp = ptr->fore; *last = ptr->next; - REMOVE_ENTRY(table, ptr); + remove_entry(table, ptr); free(ptr); break; } @@ -820,9 +826,7 @@ st_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) case ST_STOP: return 0; case ST_DELETE: - table->num_entries--; - memmove(&table->bins[i*2], &table->bins[(i+1)*2], - sizeof(struct st_table_entry*) * 2*(table->num_entries-i)); + remove_packed_entry(table, i); i--; break; } @@ -863,7 +867,7 @@ st_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) if (ptr == tmp) { tmp = ptr->fore; *last = ptr->next; - REMOVE_ENTRY(table, ptr); + remove_entry(table, ptr); free(ptr); if (ptr == tmp) return 0; ptr = tmp; @@ -908,9 +912,7 @@ st_reverse_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) case ST_STOP: return 0; case ST_DELETE: - table->num_entries--; - memmove(&table->bins[i*2], &table->bins[(i+1)*2], - sizeof(struct st_table_entry*) * 2*(table->num_entries-i)); + remove_packed_entry(table, i); break; } } @@ -943,7 +945,7 @@ st_reverse_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) if (ptr == tmp) { tmp = ptr->back; *last = ptr->next; - REMOVE_ENTRY(table, ptr); + remove_entry(table, ptr); free(ptr); ptr = tmp; break; From f92af2b7c1a0c8c51068e0a537b9857eb29ee2ec Mon Sep 17 00:00:00 2001 From: Sokolov Yura Date: Thu, 5 Jan 2012 14:20:56 +0400 Subject: [PATCH 2/5] st macroses for packed table --- st.c | 92 ++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 49 insertions(+), 43 deletions(-) diff --git a/st.c b/st.c index 9f2432d81cf056..01687f62b938b0 100644 --- a/st.c +++ b/st.c @@ -27,6 +27,8 @@ struct st_table_entry { #define ST_DEFAULT_MAX_DENSITY 5 #define ST_DEFAULT_INIT_TABLE_SIZE 11 +#define ST_DEFAULT_SECOND_TABLE_SIZE 19 +#define MAX_PACKED_NUMHASH (ST_DEFAULT_INIT_TABLE_SIZE/2) /* * DEFAULT_MAX_DENSITY is the default for the largest we allow the @@ -76,6 +78,24 @@ static void rehash(st_table *); #define do_hash(key,table) (unsigned int)(st_index_t)(*(table)->type->hash)((key)) #define do_hash_bin(key,table) (do_hash((key), (table))%(table)->num_bins) +/* preparation for possible packing improvements */ +#define PKEY_POS(i, num_bins) ((i)*2) +#define PVAL_POS(i, num_bins) ((i)*2+1) +#define PKEY(table, i) (st_data_t)(table)->bins[PKEY_POS(i, (table)->num_bins)] +#define PVAL(table, i) (st_data_t)(table)->bins[PVAL_POS(i, (table)->num_bins)] +#define PKEY_SET(table, i, v) do{ (table)->bins[PKEY_POS(i, (table)->num_bins)] = (st_table_entry *)(v); } while(0) +#define PVAL_SET(table, i, v) do{ (table)->bins[PVAL_POS(i, (table)->num_bins)] = (st_table_entry *)(v); } while(0) +/* this function depends much on packed layout, so that it placed here */ +static inline void +remove_packed_entry(st_table *table, st_index_t i) +{ + table->num_entries--; + if (i < table->num_entries) { + memmove(table->bins + 2*i, table->bins + 2*(i+1), + sizeof(st_table_entry *) * 2 * (table->num_entries - i)); + } +} + /* * MINSIZE is the minimum size of a dictionary. */ @@ -87,7 +107,7 @@ Table of prime numbers 2^n+a, 2<=n<=30. */ static const unsigned int primes[] = { ST_DEFAULT_INIT_TABLE_SIZE, - 16 + 3, + ST_DEFAULT_SECOND_TABLE_SIZE, 32 + 5, 64 + 3, 128 + 3, @@ -162,8 +182,6 @@ stat_col(void) } #endif -#define MAX_PACKED_NUMHASH (ST_DEFAULT_INIT_TABLE_SIZE/2) - st_table* st_init_table_with_size(const struct st_hash_type *type, st_index_t size) { @@ -326,7 +344,7 @@ static inline st_index_t find_packed_index(st_table *table, st_data_t key) { st_index_t i = 0; - while (i < table->num_entries && (st_data_t)table->bins[i*2] != key) i++; + while (i < table->num_entries && PKEY(table, i) != key) i++; return i; } @@ -341,7 +359,7 @@ st_lookup(st_table *table, register st_data_t key, st_data_t *value) if (table->entries_packed) { st_index_t i = find_packed_index(table, key); if (i < table->num_entries) { - if (value != 0) *value = (st_data_t)table->bins[i*2+1]; + if (value != 0) *value = PVAL(table, i); return 1; } return 0; @@ -368,7 +386,7 @@ st_get_key(st_table *table, register st_data_t key, st_data_t *result) if (table->entries_packed) { st_index_t i = find_packed_index(table, key); if (i < table->num_entries) { - if (result != 0) *result = (st_data_t)table->bins[i*2]; + if (result != 0) *result = PKEY(table, i); return 1; } return 0; @@ -389,10 +407,6 @@ st_get_key(st_table *table, register st_data_t key, st_data_t *result) #undef collision_check #define collision_check 1 -#define MORE_PACKABLE_P(table) \ - ((st_index_t)((table)->num_entries+1) * 2 <= (table)->num_bins && \ - (table)->num_entries+1 <= MAX_PACKED_NUMHASH) - static void add_direct(st_table * table, st_data_t key, st_data_t value, st_index_t hash_val, st_index_t bin_pos) @@ -426,16 +440,18 @@ static void unpack_entries(register st_table *table) { st_index_t i; - struct st_table_entry *packed_bins[MAX_PACKED_NUMHASH*2]; + struct st_table_entry *packed_bins[ST_DEFAULT_INIT_TABLE_SIZE]; st_table tmp_table = *table; - memcpy(packed_bins, table->bins, sizeof(struct st_table_entry *) * table->num_entries*2); + memcpy(packed_bins, table->bins, sizeof(st_table_entry *) * ST_DEFAULT_INIT_TABLE_SIZE); table->bins = packed_bins; tmp_table.entries_packed = 0; tmp_table.num_entries = 0; memset(tmp_table.bins, 0, sizeof(struct st_table_entry *) * tmp_table.num_bins); for (i = 0; i < table->num_entries; i++) { - st_insert(&tmp_table, (st_data_t)packed_bins[i*2], (st_data_t)packed_bins[i*2+1]); + st_index_t hash_val = PKEY(table, i); /* do_hash(PKEY(table, i), &tmp_table); */ + add_direct(&tmp_table, PKEY(table, i), PVAL(table, i), + hash_val, hash_val % tmp_table.num_bins); } *table = tmp_table; } @@ -444,10 +460,10 @@ static int add_packed_direct(st_table *table, st_data_t key, st_data_t value) { int res = 1; - if (MORE_PACKABLE_P(table)) { + if (table->num_entries < MAX_PACKED_NUMHASH) { st_index_t i = table->num_entries++; - table->bins[i*2] = (struct st_table_entry*)key; - table->bins[i*2+1] = (struct st_table_entry*)value; + PKEY_SET(table, i, key); + PVAL_SET(table, i, value); } else { unpack_entries(table); @@ -466,7 +482,7 @@ st_insert(register st_table *table, register st_data_t key, st_data_t value) if (table->entries_packed) { st_index_t i = find_packed_index(table, key); if (i < table->num_entries) { - table->bins[i*2+1] = (struct st_table_entry*)value; + PVAL_SET(table, i, value); return 1; } if (add_packed_direct(table, key, value)) { @@ -498,7 +514,7 @@ st_insert2(register st_table *table, register st_data_t key, st_data_t value, if (table->entries_packed) { st_index_t i = find_packed_index(table, key); if (i < table->num_entries) { - table->bins[i*2+1] = (struct st_table_entry*)value; + PVAL_SET(table, i, value); return 1; } if (add_packed_direct(table, key, value)) { @@ -626,16 +642,6 @@ remove_entry(st_table *table, st_table_entry *ptr) table->num_entries--; } -static inline void -remove_packed_entry(st_table *table, st_index_t pos) -{ - table->num_entries--; - if (pos < table->num_entries) { - memmove(&table->bins[pos*2], &table->bins[(pos+1)*2], - sizeof(struct st_table_entry*) * 2*(table->num_entries-pos)); - } -} - int st_delete(register st_table *table, register st_data_t *key, st_data_t *value) { @@ -646,7 +652,7 @@ st_delete(register st_table *table, register st_data_t *key, st_data_t *value) if (table->entries_packed) { st_index_t i = find_packed_index(table, *key); if (i < table->num_entries) { - if (value != 0) *value = (st_data_t)table->bins[i*2+1]; + if (value != 0) *value = PVAL(table, i); remove_packed_entry(table, i); return 1; } @@ -680,8 +686,8 @@ st_delete_safe(register st_table *table, register st_data_t *key, st_data_t *val if (table->entries_packed) { st_index_t i = find_packed_index(table, *key); if (i < table->num_entries) { - if (value != 0) *value = (st_data_t)table->bins[i*2+1]; - table->bins[i*2] = (void *)never; + if (value != 0) *value = PVAL(table, i); + PKEY_SET(table, i, never); return 1; } if (value != 0) *value = 0; @@ -713,13 +719,13 @@ st_cleanup_safe(st_table *table, st_data_t never) if (table->entries_packed) { st_index_t i = 0, j = 0; - while ((st_data_t)table->bins[i*2] != never) { + while (PKEY(table, i) != never) { if (i++ == table->num_entries) return; } for (j = i; ++i < table->num_entries;) { - if ((st_data_t)table->bins[i*2] == never) continue; - table->bins[j*2] = table->bins[i*2]; - table->bins[j*2+1] = table->bins[i*2+1]; + if (PKEY(table, i) == never) continue; + PKEY_SET(table, j, PKEY(table, i)); + PVAL_SET(table, j, PVAL(table, i)); j++; } table->num_entries = j; @@ -751,10 +757,10 @@ st_update(st_table *table, st_data_t key, int (*func)(st_data_t key, st_data_t * if (table->entries_packed) { st_index_t i = find_packed_index(table, key); if (i < table->num_entries) { - value = (st_data_t)table->bins[i*2+1]; + value = PVAL(table, i); switch ((*func)(key, &value, arg)) { case ST_CONTINUE: - table->bins[i*2+1] = (struct st_table_entry*)value; + PVAL_SET(table, i, value); break; case ST_DELETE: remove_packed_entry(table, i); @@ -805,14 +811,14 @@ st_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) for (i = 0; i < table->num_entries; i++) { st_index_t j; st_data_t key, val; - key = (st_data_t)table->bins[i*2]; - val = (st_data_t)table->bins[i*2+1]; + key = PKEY(table, i); + val = PVAL(table, i); retval = (*func)(key, val, arg); if (!table->entries_packed) goto unpacked; switch (retval) { case ST_CHECK: /* check if hash is modified during iteration */ for (j = 0; j < table->num_entries; j++) { - if ((st_data_t)table->bins[j*2] == key) + if (PKEY(table, j) == key) break; } if (j == table->num_entries) { @@ -892,13 +898,13 @@ st_reverse_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) for (i = table->num_entries-1; 0 <= i; i--) { int j; st_data_t key, val; - key = (st_data_t)table->bins[i*2]; - val = (st_data_t)table->bins[i*2+1]; + key = PKEY(table, i); + val = PVAL(table, i); retval = (*func)(key, val, arg); switch (retval) { case ST_CHECK: /* check if hash is modified during iteration */ for (j = 0; j < table->num_entries; j++) { - if ((st_data_t)table->bins[j*2] == key) + if (PKEY(table, j) == key) break; } if (j == table->num_entries) { From faf83e360e7cc7a0b2b2e3e4d95d8fbc6df9838a Mon Sep 17 00:00:00 2001 From: Sokolov Yura Date: Thu, 5 Jan 2012 13:58:02 +0400 Subject: [PATCH 3/5] st macroses for allocation --- st.c | 56 +++++++++++++++++++++++++++++++++----------------------- 1 file changed, 33 insertions(+), 23 deletions(-) diff --git a/st.c b/st.c index 01687f62b938b0..9e16197dc8ba24 100644 --- a/st.c +++ b/st.c @@ -64,20 +64,33 @@ static void rehash(st_table *); #ifdef RUBY #define malloc xmalloc #define calloc xcalloc +#define realloc xrealloc #define free(x) xfree(x) #endif #define numberof(array) (int)(sizeof(array) / sizeof((array)[0])) -#define alloc(type) (type*)malloc((size_t)sizeof(type)) -#define Calloc(n,s) (char*)calloc((n),(s)) - #define EQUAL(table,x,y) ((x)==(y) || (*(table)->type->compare)((x),(y)) == 0) /* remove cast to unsigned int in the future */ #define do_hash(key,table) (unsigned int)(st_index_t)(*(table)->type->hash)((key)) #define do_hash_bin(key,table) (do_hash((key), (table))%(table)->num_bins) +/* preparation for possible allocation improvements */ +#define st_alloc_entry() (st_table_entry *)malloc(sizeof(st_table_entry)) +#define st_free_entry(entry) free(entry) +#define st_alloc_table() (st_table *)malloc(sizeof(st_table)) +#define st_dealloc_table(table) free(table) +#define st_alloc_bins(size) (st_table_entry **)calloc(size, sizeof(st_table_entry *)) +#define st_free_bins(bins, size) free(bins) +static inline st_table_entry** +st_realloc_bins(st_table_entry **bins, st_index_t newsize, st_index_t oldsize) +{ + bins = (st_table_entry **) realloc(bins, newsize * sizeof(st_table_entry *)); + memset(bins, 0, newsize * sizeof(st_table_entry *)); + return bins; +} + /* preparation for possible packing improvements */ #define PKEY_POS(i, num_bins) ((i)*2) #define PVAL_POS(i, num_bins) ((i)*2+1) @@ -202,12 +215,12 @@ st_init_table_with_size(const struct st_hash_type *type, st_index_t size) size = new_size(size); /* round up to prime number */ - tbl = alloc(st_table); + tbl = st_alloc_table(); tbl->type = type; tbl->num_entries = 0; tbl->entries_packed = type == &type_numhash && size/2 <= MAX_PACKED_NUMHASH; tbl->num_bins = size; - tbl->bins = (st_table_entry **)Calloc(size, sizeof(st_table_entry*)); + tbl->bins = st_alloc_bins(size); tbl->head = 0; tbl->tail = 0; @@ -272,7 +285,7 @@ st_clear(st_table *table) table->bins[i] = 0; while (ptr != 0) { next = ptr->next; - free(ptr); + st_free_entry(ptr); ptr = next; } } @@ -285,8 +298,8 @@ void st_free_table(st_table *table) { st_clear(table); - free(table->bins); - free(table); + st_free_bins(table->bins, table->num_bins); + st_dealloc_table(table); } size_t @@ -417,7 +430,7 @@ add_direct(st_table * table, st_data_t key, st_data_t value, bin_pos = hash_val % table->num_bins; } - entry = alloc(st_table_entry); + entry = st_alloc_entry(); entry->hash = hash_val; entry->key = key; @@ -557,12 +570,10 @@ static void rehash(register st_table *table) { register st_table_entry *ptr, **new_bins; - st_index_t i, new_num_bins, hash_val; + st_index_t new_num_bins, hash_val; new_num_bins = new_size(table->num_bins+1); - new_bins = (st_table_entry**) - xrealloc(table->bins, new_num_bins * sizeof(st_table_entry*)); - for (i = 0; i < new_num_bins; ++i) new_bins[i] = 0; + new_bins = st_realloc_bins(table->bins, new_num_bins, table->num_bins); table->num_bins = new_num_bins; table->bins = new_bins; @@ -583,17 +594,16 @@ st_copy(st_table *old_table) st_index_t num_bins = old_table->num_bins; st_index_t hash_val; - new_table = alloc(st_table); + new_table = st_alloc_table(); if (new_table == 0) { return 0; } *new_table = *old_table; - new_table->bins = (st_table_entry**) - Calloc((unsigned)num_bins, sizeof(st_table_entry*)); + new_table->bins = st_alloc_bins(num_bins); if (new_table->bins == 0) { - free(new_table); + st_dealloc_table(new_table); return 0; } @@ -606,7 +616,7 @@ st_copy(st_table *old_table) prev = 0; tail = &new_table->head; do { - entry = alloc(st_table_entry); + entry = st_alloc_entry(); if (entry == 0) { st_free_table(new_table); return 0; @@ -668,7 +678,7 @@ st_delete(register st_table *table, register st_data_t *key, st_data_t *value) remove_entry(table, ptr); if (value != 0) *value = ptr->record; *key = ptr->key; - free(ptr); + st_free_entry(ptr); return 1; } } @@ -738,7 +748,7 @@ st_cleanup_safe(st_table *table, st_data_t never) if (ptr->key == never) { tmp = ptr; *last = ptr = ptr->next; - free(tmp); + st_free_entry(tmp); } else { ptr = *(last = &ptr->next); @@ -790,7 +800,7 @@ st_update(st_table *table, st_data_t key, int (*func)(st_data_t key, st_data_t * tmp = ptr->fore; *last = ptr->next; remove_entry(table, ptr); - free(ptr); + st_free_entry(ptr); break; } } @@ -874,7 +884,7 @@ st_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) tmp = ptr->fore; *last = ptr->next; remove_entry(table, ptr); - free(ptr); + st_free_entry(ptr); if (ptr == tmp) return 0; ptr = tmp; break; @@ -952,7 +962,7 @@ st_reverse_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) tmp = ptr->back; *last = ptr->next; remove_entry(table, ptr); - free(ptr); + st_free_entry(ptr); ptr = tmp; break; } From 44c7d23544180a8ca8d3efe5f1d6b45a26d9f4c2 Mon Sep 17 00:00:00 2001 From: Sokolov Yura Date: Thu, 5 Jan 2012 19:53:04 +0300 Subject: [PATCH 4/5] st refactor add_packed_direct a bit --- st.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/st.c b/st.c index 9e16197dc8ba24..aa0da569ab3449 100644 --- a/st.c +++ b/st.c @@ -469,10 +469,9 @@ unpack_entries(register st_table *table) *table = tmp_table; } -static int +static void add_packed_direct(st_table *table, st_data_t key, st_data_t value) { - int res = 1; if (table->num_entries < MAX_PACKED_NUMHASH) { st_index_t i = table->num_entries++; PKEY_SET(table, i, key); @@ -480,9 +479,8 @@ add_packed_direct(st_table *table, st_data_t key, st_data_t value) } else { unpack_entries(table); - res = 0; + add_direct(table, key, value, key, key % table->num_bins); } - return res; } @@ -498,9 +496,8 @@ st_insert(register st_table *table, register st_data_t key, st_data_t value) PVAL_SET(table, i, value); return 1; } - if (add_packed_direct(table, key, value)) { - return 0; - } + add_packed_direct(table, key, value); + return 0; } hash_val = do_hash(key, table); @@ -530,9 +527,8 @@ st_insert2(register st_table *table, register st_data_t key, st_data_t value, PVAL_SET(table, i, value); return 1; } - if (add_packed_direct(table, key, value)) { - return 0; - } + add_packed_direct(table, key, value); + return 0; } hash_val = do_hash(key, table); @@ -556,9 +552,8 @@ st_add_direct(st_table *table, st_data_t key, st_data_t value) st_index_t hash_val, bin_pos; if (table->entries_packed) { - if (add_packed_direct(table, key, value)) { - return; - } + add_packed_direct(table, key, value); + return; } hash_val = do_hash(key, table); From 042b8b51503c3e0333acbd8d74d61b75efc5f8ee Mon Sep 17 00:00:00 2001 From: Sokolov Yura Date: Sun, 8 Jan 2012 19:55:05 +0400 Subject: [PATCH 5/5] st optimize st_insert --- st.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/st.c b/st.c index aa0da569ab3449..48fe5659932f5e 100644 --- a/st.c +++ b/st.c @@ -420,11 +420,11 @@ st_get_key(st_table *table, register st_data_t key, st_data_t *result) #undef collision_check #define collision_check 1 -static void +static inline void add_direct(st_table * table, st_data_t key, st_data_t value, - st_index_t hash_val, st_index_t bin_pos) + st_index_t hash_val, register st_index_t bin_pos) { - st_table_entry *entry; + register st_table_entry *entry; if (table->num_entries > ST_DEFAULT_MAX_DENSITY * table->num_bins) { rehash(table); bin_pos = hash_val % table->num_bins; @@ -432,10 +432,11 @@ add_direct(st_table * table, st_data_t key, st_data_t value, entry = st_alloc_entry(); + entry->next = table->bins[bin_pos]; + table->bins[bin_pos] = entry; entry->hash = hash_val; entry->key = key; entry->record = value; - entry->next = table->bins[bin_pos]; if (table->head != 0) { entry->fore = 0; (entry->back = table->tail)->fore = entry; @@ -445,7 +446,6 @@ add_direct(st_table * table, st_data_t key, st_data_t value, table->head = table->tail = entry; entry->fore = entry->back = 0; } - table->bins[bin_pos] = entry; table->num_entries++; } @@ -487,7 +487,8 @@ add_packed_direct(st_table *table, st_data_t key, st_data_t value) int st_insert(register st_table *table, register st_data_t key, st_data_t value) { - st_index_t hash_val, bin_pos; + st_index_t hash_val; + register st_index_t bin_pos; register st_table_entry *ptr; if (table->entries_packed) { @@ -518,7 +519,8 @@ int st_insert2(register st_table *table, register st_data_t key, st_data_t value, st_data_t (*func)(st_data_t)) { - st_index_t hash_val, bin_pos; + st_index_t hash_val; + register st_index_t bin_pos; register st_table_entry *ptr; if (table->entries_packed) { @@ -549,7 +551,7 @@ st_insert2(register st_table *table, register st_data_t key, st_data_t value, void st_add_direct(st_table *table, st_data_t key, st_data_t value) { - st_index_t hash_val, bin_pos; + st_index_t hash_val; if (table->entries_packed) { add_packed_direct(table, key, value); @@ -557,8 +559,7 @@ st_add_direct(st_table *table, st_data_t key, st_data_t value) } hash_val = do_hash(key, table); - bin_pos = hash_val % table->num_bins; - add_direct(table, key, value, hash_val, bin_pos); + add_direct(table, key, value, hash_val, hash_val % table->num_bins); } static void