Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++(哈希)地图速度优化_C++_Performance_Hashmap - Fatal编程技术网

C++(哈希)地图速度优化

C++(哈希)地图速度优化,c++,performance,hashmap,C++,Performance,Hashmap,我正在创建一个游戏,但我在地图性能方面遇到了问题 在每次渲染/更新调用中,我都必须循环遍历列表中的每个块。 当我移动到块边界上时,一些需要添加或删除的块将被逐个添加和删除到列表中 这花费的时间太长,影响了我的游戏表现。如果我删除更新循环,我的FPS将增加100 for(pair<const DWORD, Chunk*>& pair : loadedChunks){ Chunk* c = pair.second; if(c != NULL){ c

我正在创建一个游戏,但我在地图性能方面遇到了问题

在每次渲染/更新调用中,我都必须循环遍历列表中的每个块。 当我移动到块边界上时,一些需要添加或删除的块将被逐个添加和删除到列表中

这花费的时间太长,影响了我的游戏表现。如果我删除更新循环,我的FPS将增加100

for(pair<const DWORD, Chunk*>& pair : loadedChunks){
    Chunk* c = pair.second;
    if(c != NULL){
        c->update(delta); //Does totally nothing
    }
}
输出时间在1到2毫秒之间。这大约是我渲染所需的时间。。只是为了循环浏览205个项目的列表

编辑2:

我决定通过添加计时器来减少循环的数量:

tickTimer+=delta;
if(tickTimer >= 0.05){
    for(pair<const DWORD, Chunk*>& pair : loadedChunks){
        pair.second->update(delta);
    }
    tickTimer = 0;
}
这样,它每秒只运行20次

编辑3:


@brianbeuning有一个很好的观点,我使用的是MSV,使用的是调试模式,这样所有的代码运行速度都很慢。

如果迭代速度很重要,尝试使用地图而不是无序的地图-无序的地图可以让你更快地查找/插入/删除,但代价是更大的内存使用和整个地图上更慢的迭代。

我的精神力量表明地图中的项目比你想象的要多。也许程序中其他地方的一个bug没有从映射中删除项目

修改主循环:

int count = 0;
int nullcount = 0;
for(pair<const DWORD, Chunk*>& pair : loadedChunks){
    Chunk* c = pair.second;
    if(c != NULL){
        c->update(delta);
        count++;
    }
    else {
        nullcount++;
    }
}
unsigned int timepassed = clock() - start;
OutputDebugString((LPCWSTR) wstring(to_wstring(timepassed) + L"  items:" +  to_wstring(count) + L"   nullitems" +  to_wstring(nullcount) + L"\n").c_str());

现在它打印什么?

好吧,我不知道您在优化中使用的编译器有多好,但是您在removeChunk和getChunkAt中对同一个东西进行了两次评估。例如,在GetChunks中,首先应该存储loadedChunks.find返回的迭代器,然后在单独的语句测试中,如果它为NULL,则返回它的->second。您可以在removeChunk中进行类似的优化


顺便说一句,我不知道你在代码的其他地方做了什么,但是在addChunk中你创建了一个新的块,保存在rebuildChunks中,并把它放在loadedChunks映射中。但是,在removeChunk中,您可以使用loadedChunks[key]中的指针删除块,但代码段中没有任何内容可以从重建块中删除块。如果它仍然在那里,你就有一个悬空的指针……

只是在列表中循环需要很长时间。正如您在第一段代码中所看到的,update方法完全没有注意到这一点,因此无法降低FPS。@ParkYoung Bae我在FPS指示符块的基础上添加了一点编辑,是多态基类吗?如果不是,则不需要间接寻址。只需将Chuck而不是Chuck*存储为值。如果您使用调试模式代码进行开发,则STL代码在调试模式下的速度要慢得多。@Duckdoom5版本当然更快。这就是整个发布点:我希望一个由小键和值组成的映射的内存开销相当大,并且比散列映射的内存开销更零碎。我想这才是真正需要衡量的事情。我以前使用过一个映射,这更糟糕,因为我还需要在加载getChunkAt和移动addChunk时快速访问数据,在整个映射上移除ChunkSlow迭代。对散列容器中所有元素的迭代与对列表的迭代几乎相同nullitems0@Duckdoom5-对不起。我的超能力让我失望了。但我有另一个选择给你。您可以使用我的fasthash模板类。这是一个经典的哈希表实现,但它只分配一次内存,这意味着您在构造函数中为它指定元素的最大大小或作为模板参数。它是为一个服务器项目编写的,其中std::*集合类由于不确定的内存分配而性能较差。代码在:处,示例在:处看起来很有趣,如果我的最新方法不起作用,我会试试。谢谢你的小改进。这是重建代码:static double timerr=0;void ChunkManager::rebuildduble delta,Renderer&Renderer{iftimerr>0{timerr-=delta;}否则!rebuildChunks.empty{rebuildChunks.back->initializenderer;rebuildChunks.pop_back;timerr=0.01;}如您所见,它已被删除。
tickTimer+=delta;
if(tickTimer >= 0.05){
    for(pair<const DWORD, Chunk*>& pair : loadedChunks){
        pair.second->update(delta);
    }
    tickTimer = 0;
}
int count = 0;
int nullcount = 0;
for(pair<const DWORD, Chunk*>& pair : loadedChunks){
    Chunk* c = pair.second;
    if(c != NULL){
        c->update(delta);
        count++;
    }
    else {
        nullcount++;
    }
}
unsigned int timepassed = clock() - start;
OutputDebugString((LPCWSTR) wstring(to_wstring(timepassed) + L"  items:" +  to_wstring(count) + L"   nullitems" +  to_wstring(nullcount) + L"\n").c_str());