性能下降 - 可能是设计糟糕的方法

时间:2013-02-21 09:53:40

标签: c++ performance vector

我正在开发基于客户端 - 服务器平铺的游戏。客户端以三维std::vector保存数据,并在每个帧中将其内容与服务器发送的内容进行比较(我在客户端有一个单独的std::vector,其中填充了服务器发送的数据)。

现在客户端的地图由15x11个图块组成,每个图块包含放置在其上的10个对象的数据,因此我在std::vector中得到15 * 11 * 10 = 1650个元素。

我正在比较两个std::vector中的数据,如果发生了变化,我会创建新的对象/删除对象/移动对象,具体取决于差异。我就是这样做的:

std::vector<IdAndPosition> clientIds; 
std::vector<IdAndPosition> serverIds;

// Fill client ids
for(unsigned int i = 0; i < m_tiles.size(); i++)
{
    for(unsigned int j = 0; j < m_tiles[i].size(); j++)
    {   
        for(unsigned int s = 0; s < m_tiles[i][j].getObjects().size(); s++)
        {
            clientIds.push_back(IdAndPosition(m_tiles[i][j].getObjectAtPosition(s)->getId(), i, j, s));
        }
    }
}

// Fill server ids
for(unsigned int i = 0; i < g_gameStateData.m_gameObjects.size(); i++)
{
    for(unsigned int j = 0; j < g_gameStateData.m_gameObjects[i].size(); j++)
    {   
        for(unsigned int s = 0; s < g_gameStateData.m_gameObjects[i][j].size(); s++)
        {
            serverIds.push_back(IdAndPosition(g_gameStateData.m_gameObjects[i][j][s].second, i, j, s));
        }
    }
}

for (int i = 0; i < serverIds.size(); i++)
{
    IdAndPosition& serverId = serverIds[i];

    bool found = false;
    for(int j = 0; j < clientIds.size(); j++)
    {
        IdAndPosition& clientId = clientIds[j];

        found = serverId.id == clientId.id;
        if(found)
            break;
    }
    if(!found)
    {
        // If not found, create that object
                        // tileX        // tileY
        m_tiles[serverId.pos[0]][serverId.pos[1]].addObjectAtPosition(
            TGameObjectFactory::createGameObject(g_gameStateData.m_gameObjects[serverId.pos[0]][serverId.pos[1]][serverId.pos[2]].first),   // Game object
            serverId.pos[2]                                                                                                                 // Position at stack
        );

        // And set it's individual id
        m_tiles[serverId.pos[0]][serverId.pos[1]].getObjectAtPosition(serverId.pos[2])->setId(g_gameStateData.m_gameObjects[serverId.pos[0]][serverId.pos[1]][serverId.pos[2]].second);
    }
}

for (int i = 0; i < clientIds.size(); i++)
{
    IdAndPosition& clientId = clientIds[i];

    bool found = false;
    for(int j = 0; j < serverIds.size(); j++)
    {
        IdAndPosition& serverId = serverIds[j];

        found = serverId.id == clientId.id;
        if(found)
            break;
    }
    if(!found)
    {
        // If not found, create empty object at this position
                        // tileX        // tileY
        m_tiles[clientId.pos[0]][clientId.pos[1]].addObjectAtPosition(
            TGameObjectFactory::createGameObject(NO_GAME_OBJECT_ID),        // Empty game object (we're removing deprecated one)
            clientId.pos[2]                                                 // Position at stack
        );
    }
}

问题是由于在调试模式下调用该函数(从~90到~20 fps),我的性能下降很大。我知道每帧都有相当多的数据,但我不知道如何设计它以便它不会那么慢。

我在Visual Studio 2012中使用了性能分析,以找出究竟导致最大性能下降的原因,并得到了这样的结果: enter image description here

[] operator的{​​{1}}似乎是主要原因。

2 个答案:

答案 0 :(得分:3)

您正在进行性能分析的代码,看起来像是对每个项目执行线性O(n)搜索,使整个事情成为O(n ^ 2)。

我真的不明白你想要实现的目标,但原因并不是因为std :: vector的运算符很慢,而是因为它的数量很多你正在做的时候。

我建议首先将所有clientId放在一个地图中,这会将顺序降低到O(nlogn)。可能还有其他优化方法,例如,如果您可以帮助它,请不要查看外部地图中的每个元素。

for(int j = 0; j < serverIds.size(); j++)
{
    IdAndPosition& serverId = serverIds[j];

    found = serverId.id == clientId.id;
    if(found)
        break;
}

答案 1 :(得分:3)

[](在我的MSVC ++中)的调试版本中有一些检查版本在发布时被删除了,这可能就是为什么它相对如此之高......

这是我看到的代码。

const_reference operator[](size_type _Pos) const
        {   // subscript nonmutable sequence
 #if _ITERATOR_DEBUG_LEVEL == 2
        if (size() <= _Pos)
            {   // report error
            _DEBUG_ERROR("vector subscript out of range");
            _SCL_SECURE_OUT_OF_RANGE;
            }

 #elif _ITERATOR_DEBUG_LEVEL == 1
        _SCL_SECURE_VALIDATE_RANGE(_Pos < size()); 
 #endif /* _ITERATOR_DEBUG_LEVEL */

        return (*(this->_Myfirst + _Pos));
        }

除了最后一行之外,几乎每一行都在发布。