浏览代码

Merge pull request #108932 from Nazarwadim/hash_map_final_optimization

Do not zero elements and perform fast clear in `HashMap`
Thaddeus Crews 4 周之前
父节点
当前提交
359ef8fc2b
共有 1 个文件被更改,包括 17 次插入14 次删除
  1. 17 14
      core/templates/hash_map.h

+ 17 - 14
core/templates/hash_map.h

@@ -181,8 +181,9 @@ private:
 
 
 		_size = 0;
 		_size = 0;
 		static_assert(EMPTY_HASH == 0, "Assuming EMPTY_HASH = 0 for alloc_static_zeroed call");
 		static_assert(EMPTY_HASH == 0, "Assuming EMPTY_HASH = 0 for alloc_static_zeroed call");
+
 		_hashes = reinterpret_cast<uint32_t *>(Memory::alloc_static_zeroed(sizeof(uint32_t) * capacity));
 		_hashes = reinterpret_cast<uint32_t *>(Memory::alloc_static_zeroed(sizeof(uint32_t) * capacity));
-		_elements = reinterpret_cast<HashMapElement<TKey, TValue> **>(Memory::alloc_static_zeroed(sizeof(HashMapElement<TKey, TValue> *) * capacity));
+		_elements = reinterpret_cast<HashMapElement<TKey, TValue> **>(Memory::alloc_static(sizeof(HashMapElement<TKey, TValue> *) * capacity));
 
 
 		if (old_capacity == 0) {
 		if (old_capacity == 0) {
 			// Nothing to do.
 			// Nothing to do.
@@ -208,7 +209,7 @@ private:
 
 
 			static_assert(EMPTY_HASH == 0, "Assuming EMPTY_HASH = 0 for alloc_static_zeroed call");
 			static_assert(EMPTY_HASH == 0, "Assuming EMPTY_HASH = 0 for alloc_static_zeroed call");
 			_hashes = reinterpret_cast<uint32_t *>(Memory::alloc_static_zeroed(sizeof(uint32_t) * capacity));
 			_hashes = reinterpret_cast<uint32_t *>(Memory::alloc_static_zeroed(sizeof(uint32_t) * capacity));
-			_elements = reinterpret_cast<HashMapElement<TKey, TValue> **>(Memory::alloc_static_zeroed(sizeof(HashMapElement<TKey, TValue> *) * capacity));
+			_elements = reinterpret_cast<HashMapElement<TKey, TValue> **>(Memory::alloc_static(sizeof(HashMapElement<TKey, TValue> *) * capacity));
 		}
 		}
 
 
 		if (_size + 1 > MAX_OCCUPANCY * capacity) {
 		if (_size + 1 > MAX_OCCUPANCY * capacity) {
@@ -235,6 +236,15 @@ private:
 		return elem;
 		return elem;
 	}
 	}
 
 
+	void _clear_data() {
+		HashMapElement<TKey, TValue> *current = _tail_element;
+		while (current != nullptr) {
+			HashMapElement<TKey, TValue> *prev = current->prev;
+			Allocator::delete_allocation(current);
+			current = prev;
+		}
+	}
+
 public:
 public:
 	_FORCE_INLINE_ uint32_t get_capacity() const { return hash_table_size_primes[_capacity_idx]; }
 	_FORCE_INLINE_ uint32_t get_capacity() const { return hash_table_size_primes[_capacity_idx]; }
 	_FORCE_INLINE_ uint32_t size() const { return _size; }
 	_FORCE_INLINE_ uint32_t size() const { return _size; }
@@ -249,16 +259,9 @@ public:
 		if (_elements == nullptr || _size == 0) {
 		if (_elements == nullptr || _size == 0) {
 			return;
 			return;
 		}
 		}
-		uint32_t capacity = hash_table_size_primes[_capacity_idx];
-		for (uint32_t i = 0; i < capacity; i++) {
-			if (_hashes[i] == EMPTY_HASH) {
-				continue;
-			}
 
 
-			_hashes[i] = EMPTY_HASH;
-			Allocator::delete_allocation(_elements[i]);
-			_elements[i] = nullptr;
-		}
+		_clear_data();
+		memset(_hashes, EMPTY_HASH, get_capacity() * sizeof(uint32_t));
 
 
 		_tail_element = nullptr;
 		_tail_element = nullptr;
 		_head_element = nullptr;
 		_head_element = nullptr;
@@ -356,7 +359,6 @@ public:
 		}
 		}
 
 
 		Allocator::delete_allocation(_elements[idx]);
 		Allocator::delete_allocation(_elements[idx]);
-		_elements[idx] = nullptr;
 
 
 		_size--;
 		_size--;
 		return true;
 		return true;
@@ -385,8 +387,9 @@ public:
 			idx = next_idx;
 			idx = next_idx;
 			_increment_mod(next_idx, capacity);
 			_increment_mod(next_idx, capacity);
 		}
 		}
+
 		_hashes[idx] = EMPTY_HASH;
 		_hashes[idx] = EMPTY_HASH;
-		_elements[idx] = nullptr;
+
 		// _insert_element will increment this again.
 		// _insert_element will increment this again.
 		_size--;
 		_size--;
 
 
@@ -688,7 +691,7 @@ public:
 	}
 	}
 
 
 	~HashMap() {
 	~HashMap() {
-		clear();
+		_clear_data();
 
 
 		if (_elements != nullptr) {
 		if (_elements != nullptr) {
 			Memory::free_static(_elements);
 			Memory::free_static(_elements);