std :: vector push_back是瓶颈

时间:2010-10-23 23:55:45

标签: c++ vector

以下是我的算法: 它需要一个长的std :: string,并根据它是否大于宽度将其分为单词和子单词:

inline void extractWords(std::vector<std::string> &words, std::string &text,const AguiFont &font, int maxWidth)
{


    words.clear();

    int searchStart = 0;
    int curSearchPos = 0;
    char right;
    for(size_t i = 0; i < text.length(); ++i)
    {
        curSearchPos = i;

        //check if a space is to the right
        if( i == text.length() - 1)
            right = 'a';
        else
            right = text[i + 1];

        //sub divide the string if it;s too big
        int subStrWidth = 0;
        int subStrLen = 0;
        for(int x = searchStart; x < (curSearchPos - searchStart) + 1; ++x)
        {
            subStrWidth += font.getTextWidth(&text[x]);
            subStrLen ++;
        }
        if(subStrLen > maxWidth && subStrLen > 1)
        {
            for(int k = 2; k <= subStrLen; ++k)
            {
                subStrWidth = 0;
                for(int p = 0; p < k; ++p)
                {
                    subStrWidth += font.getTextWidth(&text[searchStart + p]);
                }
                if(subStrWidth > maxWidth)
                {
                    searchStart += k - 1;

                    words.push_back(text.substr(searchStart,k - 1));
                    break;

                }
            }
        }

        //add the word
        if((text[i] == ' ' && right != ' ' ) || i == text.length() - 1)
        {

                if(searchStart > 0)
                {
                    words.push_back(text.substr(searchStart ,(curSearchPos - searchStart) + 1));

                }
                else
                {
                    words.push_back(text.substr(0 ,(curSearchPos - searchStart) ));
                    words.back() += text[curSearchPos];

                }

            searchStart = i + 1 ;
        }
    }


}

正如你所看到的,我使用std :: vectors来推送我的话。载体通过参考给出。那个std :: vector是静态的,它在proc中调用extractWord。奇怪的是,使其静止导致更多的CPU消耗。在分析之后,我看到我正在进行大量的堆分配但是我不知道为什么因为std :: vector即使在向量被清除之后也应该保留它的项目。这样做可能不那么密集吗?字符串长度未知,结果字符串的数量也不是我选择std :: vector的原因,但是可能有更好的方法吗?

由于

*实际上我认为我的子串生成很慢

5 个答案:

答案 0 :(得分:11)

通常,如果向向量添加元素是瓶颈,则应使用std::vector<T>::reserve提前预留一些空间。这应该会降低对push_back的调用触发内存重新分配的可能性。

也就是说,字符串处理通常可能是CPU密集型的,并且重新分配字符串对象的向量需要复制 lot 。每次向量重新分配内存时,每个字符串对象都需要复制到内存中的另一个位置。 (幸运的是,一旦C ++ 0x移动构造函数到位,这将大大减轻。)

此外,每次清除向量这一事实并没有改变每次调用push_back导致将字符串对象复制到向量中的事实,这可能是所有堆分配的原因你看到了。不要忘记std::string的每个实例都需要在堆上分配内存来存储字符串。

答案 1 :(得分:0)

如果您知道结果字符串的数量,那么

矢量将是最好的,如果您不知道它,则不是。 deque或list会做得更好。 但也许你可以检查一下开始时矢量的容量是什么,最后是什么尺寸。

答案 2 :(得分:0)

您可以切换到间接保存字符串的向量。然后,不会在每次调整存储大小时复制字符串,只复制“句柄”。所以更像std::vector<std::string> &words而不是std::vector< counted_ptr<std::string> > &words。然后查看this Dobb博士的文章,了解有关counts_ptr&lt;&gt;的更多信息。

另外,为了避免潜在的Heisenbug追逐,auto_ptr&lt;&gt;是你想在STL容器中使用什么东西。

答案 3 :(得分:0)

首先,您应该考虑传递输出迭代器而不是vector&。这将使设计更清晰,更灵活。

clear()的定义不保证内存利用率。当您调用clear时,该实现完全有权释放所有已用内存。它可以合理地实现如下:

void clear() { vector tmp; swap(tmp); }

您可能会很幸运地拨打resize(0)而不是clear(),但即使这样也不需要保留矢量的容量。

如果你真的想要压缩所有这些内存分配:

  1. 将函数定义为具有输出迭代器的模板函数,如上所述,还传递计数限制。
  2. 传入一个足够大的普通C阵列,以容纳您希望看到的最大字数。
  3. 使用std::pair<const char*, const char*>代替std::string来保留找到的字词。

答案 4 :(得分:0)

代码看起来效果很好,但在性能方面,魔鬼总是处于细节之中。以下是一些想法:

  1. 考虑更改矢量声明:

    from:std :: vector&lt; std :: string&gt; &安培;词语
    to:std :: vector&lt; std :: string *&gt; &amp; words

    这将创建一个指针并为其指定一个字符串的地址,而不是将每个字符串的内容复制到向量中。

  2. 尝试使用vector :: reserve来预先分配处理字符串所需的内存。粗略估计可能是text.length()/ maxWidth。

  3. 密切注意正在使用的字符串操作。很可能有很多临时字符串被生成并立即被丢弃。找出是否发生这种情况的最好方法是逐步执行字符串操作行,看看是否有额外的字符串构造函数和复制构造函数。