Changeset 1910 for trunk/src/kmk
- Timestamp:
- Oct 22, 2008, 9:50:39 PM (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kmk/strcache2.c
r1909 r1910 36 36 #include "debug.h" 37 37 38 #ifdef _MSC_VER 39 typedef unsigned char uint8_t; 40 typedef unsigned short uint16_t; 41 typedef unsigned int uint32_t; 42 #else 43 # include <stdint.h> 44 #endif 45 38 46 #ifdef WINDOWS32 39 47 # include <io.h> … … 72 80 /* List of initialized string caches. */ 73 81 static struct strcache2 *strcache_head; 74 75 82 76 83 … … 107 114 } 108 115 109 static struct strcache2_seg *110 strcache2_new_seg (struct strcache2 *cache, unsigned int minlen)111 {112 struct strcache2_seg *seg;113 size_t size;114 size_t off;115 116 size = cache->def_seg_size;117 if (size < (size_t)minlen + sizeof (struct strcache2_seg) + STRCACHE2_ENTRY_ALIGNMENT)118 {119 size = (size_t)minlen * 2;120 size = (size + 0xfff) & ~(size_t)0xfff;121 }122 123 seg = xmalloc (size);124 seg->start = (char *)(seg + 1);125 seg->size = size - sizeof (struct strcache2_seg);126 off = (size_t)seg->start & (STRCACHE2_ENTRY_ALIGNMENT - 1);127 if (off)128 {129 seg->start += off;130 seg->size -= off;131 }132 assert (seg->size > minlen);133 seg->cursor = seg->start;134 seg->avail = seg->size;135 136 seg->next = cache->seg_head;137 cache->seg_head = seg;138 139 return seg;140 }141 142 116 MY_INLINE unsigned int 143 117 strcache2_case_sensitive_hash_1 (const char *str, unsigned int len) 144 118 { 145 119 #if 1 120 /* Paul Hsieh hash SuperFast function: 121 http://www.azillionmonkeys.com/qed/hash.html 122 123 This performs very good and as a sligtly better distribution than 124 STRING_N_HASH_1 on a typical kBuild run. 125 126 It is also 37% faster than return_STRING_N_HASH_1 when running the 127 two 100 times over typical kBuild strings that end up here (did a 128 fprintf here and built kBuild). Compiler was 32-bit gcc 4.0.1, darwin, 129 with -O2. 130 131 FIXME: A path for well aligned data should be added to speed up 132 execution on alignment sensitive systems. */ 133 134 # if defined(__amd64__) || defined(__x86_64__) || defined(__AMD64__) || defined(_M_X64) || defined(__amd64) \ 135 || defined(__i386__) || defined(__x86__) || defined(__X86__) || defined(_M_IX86) || defined(__i386) 136 # define strcache2_get_unaligned_16bits(ptr) ( *((const uint16_t *)(ptr))) 137 # else 138 /* (endian doesn't matter) */ 139 # define strcache2_get_unaligned_16bits(ptr) ( (((const uint8_t *)(ptr))[0] << 8) \ 140 | (((const uint8_t *)(ptr))[1]) ) 141 # endif 142 uint32_t hash = len; 143 uint32_t tmp; 144 int rem; 145 146 assert (sizeof (uint8_t) == sizeof (char)); 147 if (len == 0) 148 return 0; 149 150 /* main loop, walking on 2 x uint16_t */ 151 rem = len & 3; 152 len >>= 2; 153 while (len > 0) 154 { 155 hash += strcache2_get_unaligned_16bits (str); 156 tmp = (strcache2_get_unaligned_16bits (str + 2) << 11) ^ hash; 157 hash = (hash << 16) ^ tmp; 158 str += 2 * sizeof (uint16_t); 159 hash += hash >> 11; 160 len--; 161 } 162 163 /* the remainer */ 164 switch (rem) 165 { 166 case 3: 167 hash += strcache2_get_unaligned_16bits (str); 168 hash ^= hash << 16; 169 hash ^= str[sizeof (uint16_t)] << 18; 170 hash += hash >> 11; 171 break; 172 case 2: 173 hash += strcache2_get_unaligned_16bits (str); 174 hash ^= hash << 11; 175 hash += hash >> 17; 176 break; 177 case 1: 178 hash += *str; 179 hash ^= hash << 10; 180 hash += hash >> 1; 181 break; 182 } 183 184 /* force "avalanching" of final 127 bits. */ 185 hash ^= hash << 3; 186 hash += hash >> 5; 187 hash ^= hash << 4; 188 hash += hash >> 17; 189 hash ^= hash << 25; 190 hash += hash >> 6; 191 192 return hash; 193 194 #elif 1 146 195 /* Note! This implementation is 18% faster than return_STRING_N_HASH_1 147 196 when running the two 100 times over typical kBuild strings that … … 183 232 hash = 0; 184 233 return hash; 185 #else 186 # if 1 187 /* This is SDBM. This specific form and loop unroll was benchmarked to 188 be 28% faster than return_STRING_N_HASH_1. (Now the weird thing is 189 that putting the (ch) first in the assignment made it noticably slower.) 234 235 #elif 1 236 # if 0 237 /* This is SDBM. This specific form/unroll was benchmarked to be 28% faster 238 than return_STRING_N_HASH_1. (Now the weird thing is that putting the (ch) 239 first in the assignment made it noticably slower.) 190 240 191 241 However, it is noticably slower in practice, most likely because of more 192 collisions. Hrmpf.193 */ 242 collisions. Hrmpf. */ 243 194 244 # define UPDATE_HASH(ch) hash = (hash << 6) + (hash << 16) - hash + (ch) 195 245 unsigned int hash = 0; 246 196 247 # else 197 248 /* This is DJB2. This specific form/unroll was benchmarked to be 27% 198 249 fast than return_STRING_N_HASH_1. 199 250 200 Ditto. 2x Hrmpf */ 251 Ditto. */ 252 201 253 # define UPDATE_HASH(ch) hash = (hash << 5) + hash + (ch) 202 254 unsigned int hash = 5381; 203 255 # endif 256 257 204 258 while (len >= 4) 205 259 { … … 366 420 #endif /* STRCACHE2_USE_CHAINING */ 367 421 } 368 369 #ifdef _MSC_VER370 typedef unsigned int int32_t;371 #else372 # include <stdint.h>373 #endif374 422 375 423 MY_INLINE int … … 561 609 562 610 /* the simple stuff first. */ 563 if ( entry == NULL 564 || entry->hash1 != hash1 611 if ( entry->hash1 != hash1 565 612 || entry->length != length) 566 613 return 0; … … 582 629 583 630 /* the simple stuff first. */ 584 if ( entry == NULL 585 || entry->hash1 != hash1 631 if ( entry->hash1 != hash1 586 632 || entry->length != length) 587 633 return 0; … … 620 666 621 667 /* Copy the entries from the old to the new hash table. */ 668 #ifdef STRCACHE2_USE_CHAINING 669 cache->collision_count = 0; 670 while (src-- > 0) 671 { 672 struct strcache2_entry *entry = src_tab[src]; 673 while (entry) 674 { 675 struct strcache2_entry *next = entry->next; 676 unsigned int dst = STRCACHE2_MOD_IT (cache, entry->hash1); 677 if ((entry->next = dst_tab[dst]) != 0) 678 cache->collision_count++; 679 dst_tab[dst] = entry; 680 681 entry = next; 682 } 683 } 684 #else /* !STRCACHE2_USE_CHAINING */ 622 685 while (src-- > 0) 623 686 { … … 625 688 if (entry) 626 689 { 627 #ifdef STRCACHE2_USE_CHAINING628 assert(!"todo");629 #else630 690 unsigned int dst = STRCACHE2_MOD_IT (cache, entry->hash1); 631 691 if (dst_tab[dst]) … … 644 704 } 645 705 } 646 647 706 dst_tab[dst] = entry; 648 #endif 649 650 } 707 } 708 } 709 #endif /* !STRCACHE2_USE_CHAINING */ 651 710 652 711 /* That's it, just free the old table and we're done. */ 653 712 free (src_tab); 713 } 714 715 static struct strcache2_seg * 716 strcache2_new_seg (struct strcache2 *cache, unsigned int minlen) 717 { 718 struct strcache2_seg *seg; 719 size_t size; 720 size_t off; 721 722 size = cache->def_seg_size; 723 if (size < (size_t)minlen + sizeof (struct strcache2_seg) + STRCACHE2_ENTRY_ALIGNMENT) 724 { 725 size = (size_t)minlen * 2; 726 size = (size + 0xfff) & ~(size_t)0xfff; 727 } 728 729 seg = xmalloc (size); 730 seg->start = (char *)(seg + 1); 731 seg->size = size - sizeof (struct strcache2_seg); 732 off = (size_t)seg->start & (STRCACHE2_ENTRY_ALIGNMENT - 1); 733 if (off) 734 { 735 seg->start += off; 736 seg->size -= off; 737 } 738 assert (seg->size > minlen); 739 seg->cursor = seg->start; 740 seg->avail = seg->size; 741 742 seg->next = cache->seg_head; 743 cache->seg_head = seg; 744 745 return seg; 654 746 } 655 747 … … 696 788 str_copy[length] = '\0'; 697 789 698 #ifndef STRCACHE2_USE_CHAINING 790 #ifdef STRCACHE2_USE_CHAINING 791 if ((entry->next = cache->hash_tab[idx]) != 0) 792 cache->collision_count++; 793 #endif /* STRCACHE2_USE_CHAINING */ 699 794 cache->hash_tab[idx] = entry; 700 #else /* STRCACHE2_USE_CHAINING */701 if ((entry->next = cache->hash_tab[idx]) == 0)702 cache->hash_tab[idx] = entry;703 else704 {705 cache->hash_tab[idx] = entry;706 cache->collision_count++;707 }708 #endif /* STRCACHE2_USE_CHAINING */709 795 cache->count++; 710 796 if (cache->count >= cache->rehash_count) … … 1384 1470 printf (_("%s %5u (%u%%) empty hash table slots\n"), 1385 1471 prefix, chain_depths[0], (unsigned int)((100.0 * chain_depths[0]) / cache->hash_size)); 1386 printf (_("%s %5u (%u%%) in used hash table slots\n"),1472 printf (_("%s %5u (%u%%) occupied hash table slots\n"), 1387 1473 prefix, chain_depths[1], (unsigned int)((100.0 * chain_depths[1]) / cache->hash_size)); 1388 1474 for (idx = 2; idx < 32; idx++)
Note:
See TracChangeset
for help on using the changeset viewer.