diff options
author | Benjamin Kramer <benny.kra@googlemail.com> | 2011-12-27 20:35:07 +0000 |
---|---|---|
committer | Benjamin Kramer <benny.kra@googlemail.com> | 2011-12-27 20:35:07 +0000 |
commit | c894b02ae037b5fdb38e42535539d5a0e49d6c41 (patch) | |
tree | 4224ea17ee6ca28dc887aa07808cf14c1ee94f7a /lib/Support | |
parent | 91968489d718b313d4c0b912062e75a82db650e7 (diff) | |
download | external_llvm-c894b02ae037b5fdb38e42535539d5a0e49d6c41.zip external_llvm-c894b02ae037b5fdb38e42535539d5a0e49d6c41.tar.gz external_llvm-c894b02ae037b5fdb38e42535539d5a0e49d6c41.tar.bz2 |
Switch StringMap from an array of structures to a structure of arrays.
- -25% memory usage of the main table on x86_64 (was wasted in struct padding).
- no significant performance change.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@147294 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Support')
-rw-r--r-- | lib/Support/StringMap.cpp | 61 |
1 files changed, 34 insertions, 27 deletions
diff --git a/lib/Support/StringMap.cpp b/lib/Support/StringMap.cpp index a1ac512..c131fe0 100644 --- a/lib/Support/StringMap.cpp +++ b/lib/Support/StringMap.cpp @@ -39,11 +39,13 @@ void StringMapImpl::init(unsigned InitSize) { NumItems = 0; NumTombstones = 0; - TheTable = (ItemBucket*)calloc(NumBuckets+1, sizeof(ItemBucket)); - + TheTable = (StringMapEntryBase **)calloc(NumBuckets+1, + sizeof(StringMapEntryBase **) + + sizeof(unsigned)); + // Allocate one extra bucket, set it to look filled so the iterators stop at // end. - TheTable[NumBuckets].Item = (StringMapEntryBase*)2; + TheTable[NumBuckets] = (StringMapEntryBase*)2; } @@ -60,29 +62,29 @@ unsigned StringMapImpl::LookupBucketFor(StringRef Name) { } unsigned FullHashValue = HashString(Name); unsigned BucketNo = FullHashValue & (HTSize-1); - + unsigned *HashTable = (unsigned *)(TheTable + NumBuckets + 1); + unsigned ProbeAmt = 1; int FirstTombstone = -1; while (1) { - ItemBucket &Bucket = TheTable[BucketNo]; - StringMapEntryBase *BucketItem = Bucket.Item; + StringMapEntryBase *BucketItem = TheTable[BucketNo]; // If we found an empty bucket, this key isn't in the table yet, return it. if (BucketItem == 0) { // If we found a tombstone, we want to reuse the tombstone instead of an // empty bucket. This reduces probing. if (FirstTombstone != -1) { - TheTable[FirstTombstone].FullHashValue = FullHashValue; + HashTable[FirstTombstone] = FullHashValue; return FirstTombstone; } - Bucket.FullHashValue = FullHashValue; + HashTable[BucketNo] = FullHashValue; return BucketNo; } if (BucketItem == getTombstoneVal()) { // Skip over tombstones. However, remember the first one we see. if (FirstTombstone == -1) FirstTombstone = BucketNo; - } else if (Bucket.FullHashValue == FullHashValue) { + } else if (HashTable[BucketNo] == FullHashValue) { // If the full hash value matches, check deeply for a match. The common // case here is that we are only looking at the buckets (for item info // being non-null and for the full hash value) not at the items. This @@ -115,18 +117,18 @@ int StringMapImpl::FindKey(StringRef Key) const { if (HTSize == 0) return -1; // Really empty table? unsigned FullHashValue = HashString(Key); unsigned BucketNo = FullHashValue & (HTSize-1); - + unsigned *HashTable = (unsigned *)(TheTable + NumBuckets + 1); + unsigned ProbeAmt = 1; while (1) { - ItemBucket &Bucket = TheTable[BucketNo]; - StringMapEntryBase *BucketItem = Bucket.Item; + StringMapEntryBase *BucketItem = TheTable[BucketNo]; // If we found an empty bucket, this key isn't in the table yet, return. if (BucketItem == 0) return -1; if (BucketItem == getTombstoneVal()) { // Ignore tombstones. - } else if (Bucket.FullHashValue == FullHashValue) { + } else if (HashTable[BucketNo] == FullHashValue) { // If the full hash value matches, check deeply for a match. The common // case here is that we are only looking at the buckets (for item info // being non-null and for the full hash value) not at the items. This @@ -165,8 +167,8 @@ StringMapEntryBase *StringMapImpl::RemoveKey(StringRef Key) { int Bucket = FindKey(Key); if (Bucket == -1) return 0; - StringMapEntryBase *Result = TheTable[Bucket].Item; - TheTable[Bucket].Item = getTombstoneVal(); + StringMapEntryBase *Result = TheTable[Bucket]; + TheTable[Bucket] = getTombstoneVal(); --NumItems; ++NumTombstones; assert(NumItems + NumTombstones <= NumBuckets); @@ -180,6 +182,7 @@ StringMapEntryBase *StringMapImpl::RemoveKey(StringRef Key) { /// the appropriate mod-of-hashtable-size. void StringMapImpl::RehashTable() { unsigned NewSize; + unsigned *HashTable = (unsigned *)(TheTable + NumBuckets + 1); // If the hash table is now more than 3/4 full, or if fewer than 1/8 of // the buckets are empty (meaning that many are filled with tombstones), @@ -194,19 +197,23 @@ void StringMapImpl::RehashTable() { // Allocate one extra bucket which will always be non-empty. This allows the // iterators to stop at end. - ItemBucket *NewTableArray =(ItemBucket*)calloc(NewSize+1, sizeof(ItemBucket)); - NewTableArray[NewSize].Item = (StringMapEntryBase*)2; - + StringMapEntryBase **NewTableArray = + (StringMapEntryBase **)calloc(NewSize+1, sizeof(StringMapEntryBase *) + + sizeof(unsigned)); + unsigned *NewHashArray = (unsigned *)(NewTableArray + NewSize + 1); + NewTableArray[NewSize] = (StringMapEntryBase*)2; + // Rehash all the items into their new buckets. Luckily :) we already have // the hash values available, so we don't have to rehash any strings. - for (ItemBucket *IB = TheTable, *E = TheTable+NumBuckets; IB != E; ++IB) { - if (IB->Item && IB->Item != getTombstoneVal()) { + for (unsigned I = 0, E = NumBuckets; I != E; ++I) { + StringMapEntryBase *Bucket = TheTable[I]; + if (Bucket && Bucket != getTombstoneVal()) { // Fast case, bucket available. - unsigned FullHash = IB->FullHashValue; + unsigned FullHash = HashTable[I]; unsigned NewBucket = FullHash & (NewSize-1); - if (NewTableArray[NewBucket].Item == 0) { - NewTableArray[FullHash & (NewSize-1)].Item = IB->Item; - NewTableArray[FullHash & (NewSize-1)].FullHashValue = FullHash; + if (NewTableArray[NewBucket] == 0) { + NewTableArray[FullHash & (NewSize-1)] = Bucket; + NewHashArray[FullHash & (NewSize-1)] = FullHash; continue; } @@ -214,11 +221,11 @@ void StringMapImpl::RehashTable() { unsigned ProbeSize = 1; do { NewBucket = (NewBucket + ProbeSize++) & (NewSize-1); - } while (NewTableArray[NewBucket].Item); + } while (NewTableArray[NewBucket]); // Finally found a slot. Fill it in. - NewTableArray[NewBucket].Item = IB->Item; - NewTableArray[NewBucket].FullHashValue = FullHash; + NewTableArray[NewBucket] = Bucket; + NewHashArray[NewBucket] = FullHash; } } |