我已經聲明並定義了下面的HashTable類。請注意,我需要散列表的哈希表,所以我的HashEntry結構包含一個HashTable指針。公共部分並不是什麼大事,它具有傳統的哈希表函數,所以爲了簡單起見我將它們刪除了。散列表需要大量內存
enum Status{ACTIVE, DELETED, EMPTY};
enum Type{DNS_ENTRY, URL_ENTRY};
class HashTable{
private:
struct HashEntry{
std::string key;
Status current_status;
std::string ip;
int access_count;
Type entry_type;
HashTable *table;
HashEntry(
const std::string &k = std::string(),
Status s = EMPTY,
const std::string &u = std::string(),
const int &a = int(),
Type e = DNS_ENTRY,
HashTable *t = NULL
): key(k), current_status(s), ip(u), access_count(a), entry_type(e), table(t){}
};
std::vector<HashEntry> array;
int currentSize;
public:
HashTable(int size = 1181, int csz = 0): array(size), currentSize(csz){}
};
我使用二次探測和我雙倍的向量的大小在我的翻版功能時,我打array.size()/2
。當需要更大的表格大小時,使用以下列表。
int a[16] = {49663, 99907, 181031, 360461,...}
我的問題是,這個類消耗這麼多的內存。我剛剛使用地塊進行了剖析,發現它需要33MB(3300萬字節)的內存才能插入125000。需要明確的是,居然
1 insertion -> 47352 Bytes
8 insertion -> 48376 Bytes
512 insertion -> 76.27KB
1000 insertion 2MB (array size increased to 49663 here)
27000 insertion-> 8MB (array size increased to 99907 here)
64000 insertion -> 16MB (array size increased to 181031 here)
125000 insertion-> 33MB (array size increased to 360461 here)
這些可能是不必要的,但我只是想告訴你的內存使用情況輸入如何變化。正如你所看到的,當完成重新哈希時,內存使用量會增加一倍。例如,我們的初始數組大小爲1181.而我們剛剛看到了125000個元素 - > 33MB。
要調試的問題,我改變了最初的大小360461.現在127000插入不需要換湯不換藥。我看到20MB的內存與這個初始值一起使用。這仍然是巨大的,但我認爲這表明存在重新調整的問題。以下是我的rehash函數。
void HashTable::rehash(){
std::vector<HashEntry> oldArray = array;
array.resize(nextprime(array.size()));
for(int j = 0; j < array.size(); j++){
array[j].current_status = EMPTY;
}
for(int i = 0; i < oldArray.size(); i++){
if(oldArray[i].current_status == ACTIVE){
insert(oldArray[i].key);
int pos = findPos(oldArray[i].key);
array[pos] = oldArray[i];
}
}
}
int nextprime(int arraysize){
int a[16] = {49663, 99907, 181031, 360461, 720703, 1400863, 2800519, 5600533, 11200031, 22000787, 44000027};
int i = 0;
while(arraysize >= a[i]){i++;}
return a[i];
}
這是用於重新散列和其他地方的插入函數。
bool HashTable::insert(const std::string &k){
int currentPos = findPos(k);
if(isActive(currentPos)){
return false;
}
array[currentPos] = HashEntry(k, ACTIVE);
if(++currentSize > array.size()/2){
rehash();
}
return true;
}
我在做什麼錯在這裏?即使它是由重新哈希引起的,當沒有完成重新哈希時,它仍然是20MB,我相信20MB對於100k項目來說太過分了。這個散列表應該包含800萬個元素。
是否有每個條目存儲整個表的原因?如果您可以發佈將'HashTable'分配給'HashEntry'的代碼,這可能會有所幫助。 – Jason
@Jason散列表的每一項都可以在其條目中包含散列表。除了這個自我指涉的定義,我想不出任何其他的東西。當然,感謝您的幫助,但我不明白您將HashTable分配給HashEntry的含義。那些是不同的班級,他們可以分配給對方嗎? – user2694307
@Jason此外,我沒有任何嵌套的哈希表。它只是一個主散列表,它在HashEntries中的HashTable中有NULL。 – user2694307