【问题标题】:c++ Read File lines to vector<string>c++ 读取文件行到vector<string>
【发布时间】:2015-08-11 20:48:25
【问题描述】:

我用这个方法从一个文件中读取并将它放入一个字符串向量中;

std::vector<std::string> read_file_lines1(const char* filepath){
    std::vector<std::string> file;
    std::ifstream input(filepath);
    Timer timer;
    float time = 0;
    std::string line;
    int i = 0;
    while (getline(input, line)){
        timer.reset();
        file.push_back(line);
        time += timer.elapsed();
        if (i == 10000)
            std::cout << "10000 done" << std::endl;
        i = ((i + 1) % 10001);
    }
    std::cout << time << std::endl;;
    return file;
}

但我认为性能真的很差(22 秒内 20 万行)

稍加改动使其成为 vector&lt;string*&gt;(使用 file.push_back(new std::string(line)) 推送调用从 ~16 秒变为 ~1.2 秒,这是一个巨大的改进(仍然落后于我的目标)它有一个小缺点:内存使用;如果我想清除这里使用的内存,我将不得不记住创建一个循环来清除每个字符串*

现在整个方法需要6~秒,其中~5个主要用于“getline”方法中的字符串,我真的很想知道如何优化它或做出替代。

PS:我这样做确实加载了一个 3D 模型,在 Java 中使用相同的模型需要大约 0.8 秒来读取所有内容和过滤器(将“每一行放入”顶点/纹理...数组,然后将它们放入按索引顺序),所以如果我花那么多时间从 C++ 中的文件中读取每一行(在 Java/C++ 中都使用调试模式,这可能使它成为一个非常糟糕的基准,但我仍然真的很失望);

【问题讨论】:

  • "使用调试模式" -- 对非优化代码进行基准测试有什么意义?
  • “使用调试模式” 导致代码未优化。
  • 他的意思是你应该在发布模式下对构建的程序进行基准测试。
  • “使用调试模式”的意思是“请不要让这段代码跑得太快!”.

标签: c++ string performance vector input


【解决方案1】:

速度慢的主要原因是,每次达到向量容量时,您都需要重新分配内存并将所有字符串移动到新位置。使用std::deque 代替向量,双端队列不会重新分配内存,它会添加新的块。或者您可以使用reserve 方法预先分配向量,以避免重新分配。

此外,调试 c++ 代码可能比发布慢得多,尤其是在使用大量模板和/或内联代码的情况下 - 您确实需要衡量发布性能,并且您需要在整个循环中只使用一次计时器,因为我怀疑在发布中模式下你会花很多时间在定时器代码上。

另一个小的优化。而不是

    if (i == 10000)
        std::cout << "10000 done" << std::endl;
    i = ((i + 1) % 10001);

使用:

    if (i == 10000)
    {
        std::cout << "10000 done" << std::endl;
        i = 0;
    }
    ++i;

【讨论】:

  • 非常感谢。我已经在没有 cout 的情况下进行了测试,差异可以忽略不计。将尝试双端队列。我尝试了 reserve() 但通常它让它变得更慢(不知道为什么)。此外,尽管对 push_back 的性能仍然不“满意”,但现在推送指针比推送字符串要好得多。我现在主要关心的是“getLine()”需要将近 5 秒,主要是因为它附加行的方式(大部分时间都花在“string+=”调用上,所以我想知道是否有更好的选择
  • 测试debug版本的性能没有意义,先试试release版本。 cout 在您的代码中没有问题,因为您不经常这样做,但是将计时器工作放在循环之外将有助于提高性能(同样,发布版本)。指针有助于提高速度,因为移动指针要快得多,但你可以完全摆脱移动。
  • 我可以摆脱移动吗?能不能稍微扩展一下?
  • std::deque 不会在 push_back 上重新分配内存 - 当没有保留空间时,分配新的内存块,内存不是连续的,但在大多数情况下是可以的。只需用 deque 替换 vector ,其他一切都应该以相同的方式工作。
  • deque 提供了更多帮助,非常感谢。 getline 在调试中仍然需要很多时间(约 5 秒),所以我想知道是否有更好的选择,但在发布时,所有过程现在都需要半秒,所以看起来很好。另外,对于双端队列,我使用 而不是 因为性能大致相同,但我不必记住在真正酷炫之后清除内存
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-06-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多