Switch to unordered_map, slightly better performance

This commit is contained in:
Marc Gilleron 2021-09-28 22:37:37 +01:00
parent ac3ecbba14
commit 100b6d1816
2 changed files with 21 additions and 18 deletions

View File

@ -114,9 +114,9 @@ VoxelDataBlock *VoxelDataMap::get_block(Vector3i bpos) {
if (_last_accessed_block && _last_accessed_block->position == bpos) {
return _last_accessed_block;
}
unsigned int *iptr = _blocks_map.getptr(bpos);
if (iptr != nullptr) {
const unsigned int i = *iptr;
auto it = _blocks_map.find(bpos);
if (it != _blocks_map.end()) {
const unsigned int i = it->second;
#ifdef DEBUG_ENABLED
CRASH_COND(i >= _blocks.size());
#endif
@ -132,9 +132,9 @@ const VoxelDataBlock *VoxelDataMap::get_block(Vector3i bpos) const {
if (_last_accessed_block != nullptr && _last_accessed_block->position == bpos) {
return _last_accessed_block;
}
const unsigned int *iptr = _blocks_map.getptr(bpos);
if (iptr != nullptr) {
const unsigned int i = *iptr;
auto it = _blocks_map.find(bpos);
if (it != _blocks_map.end()) {
const unsigned int i = it->second;
#ifdef DEBUG_ENABLED
CRASH_COND(i >= _blocks.size());
#endif
@ -153,11 +153,11 @@ void VoxelDataMap::set_block(Vector3i bpos, VoxelDataBlock *block) {
_last_accessed_block = block;
}
#ifdef DEBUG_ENABLED
CRASH_COND(_blocks_map.has(bpos));
CRASH_COND(_blocks_map.find(bpos) != _blocks_map.end());
#endif
unsigned int i = _blocks.size();
_blocks.push_back(block);
_blocks_map.set(bpos, i);
_blocks_map.insert(std::make_pair(bpos, i));
}
void VoxelDataMap::remove_block_internal(Vector3i bpos, unsigned int index) {
@ -176,9 +176,9 @@ void VoxelDataMap::remove_block_internal(Vector3i bpos, unsigned int index) {
_blocks.pop_back();
if (index < _blocks.size()) {
unsigned int *moved_block_index = _blocks_map.getptr(moved_block->position);
CRASH_COND(moved_block_index == nullptr);
*moved_block_index = index;
auto it = _blocks_map.find(moved_block->position);
CRASH_COND(it == _blocks_map.end());
it->second = index;
}
}
@ -195,7 +195,8 @@ VoxelDataBlock *VoxelDataMap::set_block_buffer(Vector3i bpos, std::shared_ptr<Vo
}
bool VoxelDataMap::has_block(Vector3i pos) const {
return /*(_last_accessed_block != nullptr && _last_accessed_block->pos == pos) ||*/ _blocks_map.has(pos);
return /*(_last_accessed_block != nullptr && _last_accessed_block->pos == pos) ||*/
_blocks_map.find(pos) != _blocks_map.end();
}
bool VoxelDataMap::is_block_surrounded(Vector3i pos) const {

View File

@ -5,8 +5,8 @@
#include "../util/profiling.h"
#include "voxel_data_block.h"
#include <core/hash_map.h>
#include <scene/main/node.h>
#include <unordered_map>
// Infinite voxel storage by means of octants like Gridmap, within a constant LOD.
// Convenience functions to access VoxelBuffers internally will lock them to protect against multithreaded access.
@ -74,9 +74,9 @@ public:
if (_last_accessed_block && _last_accessed_block->position == bpos) {
_last_accessed_block = nullptr;
}
unsigned int *iptr = _blocks_map.getptr(bpos);
if (iptr != nullptr) {
const unsigned int i = *iptr;
auto it = _blocks_map.find(bpos);
if (it != _blocks_map.end()) {
const unsigned int i = it->second;
#ifdef DEBUG_ENABLED
CRASH_COND(i >= _blocks.size());
#endif
@ -162,8 +162,10 @@ private:
FixedArray<uint64_t, VoxelBufferInternal::MAX_CHANNELS> _default_voxel;
// Blocks stored with a spatial hash in all 3D directions.
// RELATIONSHIP = 2 because it delivers better performance with this kind of key and hash (less collisions).
HashMap<Vector3i, unsigned int, Vector3iHasher, HashMapComparatorDefault<Vector3i>, 3, 2> _blocks_map;
// Before I used Godot's HashMap with RELATIONSHIP = 2 because that delivers better performance compared to
// defaults, but it sometimes has very long stalls on removal, which std::unordered_map doesn't seem to have
// (not as badly). Also overall performance is slightly better.
std::unordered_map<Vector3i, unsigned int> _blocks_map;
std::vector<VoxelDataBlock *> _blocks;
// Voxel access will most frequently be in contiguous areas, so the same blocks are accessed.